7

如果我定义以下通用事件处理程序

trait Handles[E <: Event] {
  def handle(event: E)
}

事件类型是这样的

trait Event {

}
class InventoryItemDeactivated(val id: UUID) extends Event;

class InventoryItemCreated(val id: UUID, val name: String) extends Event;

然后我如何创建一个为这些事件中的每一个实现事件处理程序的类?我试过:

class InventoryListView extends Handles[InventoryItemCreated] with Handles[InventoryItemDeactivated] {
    def handle(event: InventoryItemCreated) = {

    }

    def handle(event: InventoryItemDeactivated) = {

    }
  }

但是 Scala 抱怨一个 trait 不能被继承两次。

我发现这个答案暗示了一个解决方案,但它似乎需要多个类(每个处理程序一个)。这真的是唯一的方法,还是有一些其他的 Scala 构造我可以用来使单个类实现多个通用事件处理程序(即使用案例类、清单或其他一些奇特的构造)?

4

2 回答 2

11

我不知道在一个类中执行此操作的方法(除了通过制作EventADT 并定义句柄来接受 type 的参数Event。但这会带走您似乎正在寻找的那种类型安全)。

我建议改用类型类模式。

trait Handles[-A, -E <: Event] {
  def handle(a: A, event: E)
}

trait Event {
  ...
}
class InventoryItemDeactivation(val id: UUID) extends Event
class InventoryItemCreation(val id: UUID, val name: String) extends Event

class InventoryListView {
  ...
}

implicit object InventoryListViewHandlesItemCreation extends 
    Handles[InventoryListView, InventoryItemCreation] = {
  def handle(v: InventoryListView, e: InventoryItemCreation) = {
    ...
  }
}

implicit object InventoryListViewHandlesItemDeactivation extends 
    Handles[InventoryListView, InventoryItemDeactivation] = {
  def handle(v: InventoryListView, e: InventoryItemDeactivation) = {
    ...
  }
}

def someMethod[A, E <: Event](a: A, e: E)
              (implicit ev: InventoryListView Handles InventoryItemCreation) = {
  ev.handle(a, e)
  ...
}
于 2011-12-20T22:18:25.680 回答
4

两种不同的方法有什么好处handle

def handle(rawEvent: Event) = rawEvent match {
  case e: InventoryItemCreated => ...
  case e: InventoryItemDeactivated => ...
}
于 2012-01-20T02:17:23.257 回答