我正在努力使用类型系统。我在第
行收到“错误:类型不匹配”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()))
}
}
答案 0 :(得分:0)
您提到的问题很容易解决:
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
来解决,以解决类型擦除问题:
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
}
}
答案 1 :(得分:0)
更改addJobs
:
def addJob[T <: Event](job: Job[T]) {
jobs = job :: jobs
}
但jobs
无效,因为Job[MessageEvent]
不是Job[Event]
。获得此功能的唯一方法是使Job
共变,但不幸的是,您无法使Job
变为共变体。
为什么不完全删除Job
的参数化并在内部使用Event
?然后,如果需要,您可以使用T <: Event
(如addJob
中的上述内容)addStep
和processEvent
。
答案 2 :(得分:0)
根据您的示例,您似乎将静态构建Job
和EventHandler
个实例。在这种情况下,你真的根本不需要这些类!
从Job
开始。这有两个作用:
T => Unit
个功能 (值得注意的是::
前置,所以步骤将按照添加顺序的相反方式执行)
如果您已经知道在事物编译时它们将是什么,那么可以完全避免在运行时(在可变列表中)构建和维护该函数列表。这很自然地通过聚合函数完成:
val job = (m: MessageEvent) => {
log.debug(m)
println(m)
somethingElse(m)
}
这意味着List[Job[Event]]
现在拥有EventHandler
(之前为List[(T => Unit)]
),而不是Job
。所以冲洗并重复......