Scala:错误类型不匹配

时间:2011-04-22 21:09:10

标签: 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()))
  }
}

3 个答案:

答案 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中的上述内容)addStepprocessEvent

答案 2 :(得分:0)

根据您的示例,您似乎将静态构建JobEventHandler个实例。在这种情况下,你真的根本不需要这些类!

Job开始。这有两个作用:

  1. 维护T => Unit个功能
  2. 列表
  3. 执行这些功能
  4. (值得注意的是::前置,所以步骤将按照添加顺序的相反方式执行)

    如果您已经知道在事物编译时它们将是什么,那么可以完全避免在运行时(在可变列表中)构建和维护该函数列表。这很自然地通过聚合函数完成:

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

    这意味着List[Job[Event]]现在拥有EventHandler(之前为List[(T => Unit)]),而不是Job。所以冲洗并重复......