Scala:错误类型不匹配

发布于 2024-11-03 02:37:18 字数 1092 浏览 0 评论 0原文

我正在与类型系统作斗争。我在该行收到“错误:类型不匹配”,

handler.addJob(job1)

它说 found "MessageEvent" required "Event"

我认为我需要以某种方式更改 addJob 方法才能传入任何具有扩展Event类型的Job,但我不知道如何做到这一点。

此外,该行

var jobs = List[Job[Event]]()

可能应该接受 Event 子类型的作业,但我又不知道该怎么做。任何帮助表示赞赏。

-埃里克

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()))
  }
}

I am struggling with the type system. I get a "error: type mismatch" at the line

handler.addJob(job1)

It says found "MessageEvent" required "Event"

I think that I need to somehow change the addJob method to pass in any Job with a type that extends Event but I can't figure out how to do that.

Also the line

var jobs = List[Job[Event]]()

should probably take a job with a subtype of Event but again I don't know how to do that. Any help is appreciated.

-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()))
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

抠脚大汉 2024-11-10 02:37:18

您提到的问题很容易解决:

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

The problems you mention are easy to fix:

class EventHandler {
  var jobs = List[Job[_]]()

  def receive(event: Event) {
    jobs.foreach {
      _.processEvent(event)
    }
  }

  def addJob(job: Job[_]) {
    jobs = job :: jobs
  }
}

But this shows another problem with the receive method: you need each job to process any Event. This can be fixed using Manifests to work around type erasure:

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
  }
}
思念绕指尖 2024-11-10 02:37:18

更改 addJobs

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

但是 jobs 不起作用,因为 Job[MessageEvent] 不是 Job[Event].实现这一点的唯一方法是使 Job 成为协变体,但不幸的是,您不能按原样使 Job 成为协变体。

为什么不完全删除 Job 的参数化并在内部使用 Event 呢?然后,如果需要,您可以将 T <: Event (如上面的 addJob)与 addStepprocessEvent 一起使用。

Changing addJobs:

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

But jobs won't work with that, since Job[MessageEvent] is not a Job[Event]. The only way to get that is to make Job co-variant, but, unfortunately, you can't make Job co-variant as it is.

Why don't you, instead, completely removes Job's parameterization and use Event internally? You can then use T <: Event (like above in addJob) with addStep and processEvent, if necessary.

笑饮青盏花 2024-11-10 02:37:18

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

作业开始。这执行两个角色:

  1. 维护 T => 的列表。 Unit 函数
  2. 执行这些函数

(还值得注意的是 :: 前置,因此步骤将以与添加顺序相反的顺序执行)

如果您已经知道编译时它们会是什么,则可以完全避免在运行时维护该函数列表(在可变列表中)。这是最自然地使用聚合函数完成的:

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

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

Based on your example, it looks as though you'll be building the Job and EventHandler instances statically. In this case, you really don't need those classes at all!

Starting with Job. This performs two roles:

  1. maintain a list of T => Unit functions
  2. execute those functions

(it's also worth noting that :: prepends, so steps will be executed in the reverse of the order they were added)

Building and maintaining that list of functions at runtime (within a mutable list) can be completely avoided if you already know what they'll be when the thing compiles. This is most naturally done with an aggregate function:

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

Instead of holding a List[Job[Event]], this means that EventHandler now holds a List[(T => Unit)] (as Job previously did). So rinse and repeat...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文