Scala:错误类型不匹配
问题描述:
我在使用类型系统挣扎。我得到一个:在该行“错误类型不匹配”Scala:错误类型不匹配
handler.addJob(job1)
它说found "MessageEvent" required "Event"
我想我需要以某种方式改变addJob
方法在任何Job
传递与延伸Event
但我一个类型无法弄清楚如何做到这一点。
还行
var jobs = List[Job[Event]]()
或许应该采取与工作的Event
一个亚型,但再次我不知道该怎么做。任何帮助表示赞赏。
-Eric
class EventHandler {
var jobs = List[Job[Event]]()
def receive(event: Event) {
jobs.foreach {
_.processEvent(event)
}
}
def addJob(job: Job[Event]) {
jobs = job :: jobs
}
}
class Job[T <: Event] {
var steps = List[(T => Unit)]()
def addStep(step: (T => Unit)) {
steps = step :: steps
}
def processEvent(event: T): Boolean = {
steps.foreach(_.apply(event))
return true
}
}
class AppTest {
def testApp {
val handler = new EventHandler()
val job1 = new Job[MessageEvent]
job1.addStep {
println(_)
}
handler.addJob(job1)
handler.receive(new MessageEvent(new Message()))
}
}
答
你提的问题是很容易解决:
class EventHandler {
var jobs = List[Job[_]]()
def receive(event: Event) {
jobs.foreach {
_.processEvent(event)
}
}
def addJob(job: Job[_]) {
jobs = job :: jobs
}
}
但是这显示了receive
方法另一个问题:你需要在每个job
处理任何Event
。这可以通过使用Manifest
s到解决类型擦除是固定的:
class Job[T <: Event : ClassManifest] {
val clazz: Class[T] = implicitly[ClassManifest[T]].asInstanceOf[Class[T]]
var steps = List[(T => Unit)]()
def addStep(step: (T => Unit)) {
steps = step :: steps
}
def processEvent1(event: Event): Boolean = {
try {
processEvent(clazz.cast(event))
}
catch {
case e: ClassCastException => false
}
}
def processEvent(event: T): Boolean = {
steps.foreach(_.apply(event))
return true
}
}
答
更改addJobs
:
def addJob[T <: Event](job: Job[T]) {
jobs = job :: jobs
}
但jobs
不会与工作,因为Job[MessageEvent]
不是Job[Event]
。唯一的方法是制作Job
联合变体,但是,不幸的是,您不能按原样制作Job
联合变体。
为什么你不完全删除Job
的参数并在内部使用Event
?然后,您可以(在addJob
像以上)使用T <: Event
与addStep
和processEvent
,如果需要的话。
答
根据您的示例,您看起来好像您将静态构建Job
和EventHandler
实例。在这种情况下,你根本不需要这些类!
与Job
开始。这将执行两个角色:
- 保持
T => Unit
函数列表 - 执行这些功能
(这也是值得注意的是::
预先考虑,所以步骤将在顺序的反向执行他们加入)
建设和维护运行时的函数列表(可变名单内)可以,如果你alread完全避免你知道他们编译时会是什么样的。这是最自然地聚合函数来完成:
val job = (m: MessageEvent) => {
log.debug(m)
println(m)
somethingElse(m)
}
而不是拿着List[Job[Event]]
,这意味着EventHandler
现在持有List[(T => Unit)]
(如Job
以前一样)。所以冲洗和重复...
非常感谢您的帮助Alexey! – user721102 2011-04-22 21:50:04
如果您喜欢答案,您应该对其进行投票(请参阅常见问题解答,“我如何在此提问?”)。 – 2011-04-23 06:11:39