2011-04-22 72 views
2

我在使用类型系统挣扎。我得到一个:在该行“错误类型不匹配”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())) 
    } 
} 

回答

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 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 
    } 
} 
+0

非常感谢您的帮助Alexey! – user721102 2011-04-22 21:50:04

+0

如果您喜欢答案,您应该对其进行投票(请参阅常见问题解答,“我如何在此提问?”)。 – 2011-04-23 06:11:39

0

更改addJobs

def addJob[T <: Event](job: Job[T]) { 
    jobs = job :: jobs 
} 

jobs不会与工作,因为Job[MessageEvent]不是Job[Event]。唯一的方法是制作Job联合变体,但是,不幸的是,您不能按原样制作Job联合变体。

为什么你不完全删除Job的参数并在内部使用Event?然后,您可以(在addJob像以上)使用T <: EventaddStepprocessEvent,如果需要的话。

0

根据您的示例,您看起来好像您将静态构建JobEventHandler实例。在这种情况下,你根本不需要这些类!

Job开始。这将执行两个角色:

  1. 保持T => Unit函数列表
  2. 执行这些功能

(这也是值得注意的是::预先考虑,所以步骤将在顺序的反向执行他们加入)

建设和维护运行时的函数列表(可变名单内)可以,如果你alread完全避免你知道他们编译时会是什么样的。这是最自然地聚合函数来完成:

val job = (m: MessageEvent) => { 
    log.debug(m) 
    println(m) 
    somethingElse(m) 
} 

而不是拿着List[Job[Event]],这意味着EventHandler现在持有List[(T => Unit)](如Job以前一样)。所以冲洗和重复...