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 は、トレイトを 2 回継承することはできないと文句を言っています。

解決策を示唆するこの回答を見つけましたが、複数のクラス (ハンドラーごとに 1 つ) が必要なようです。これが本当に唯一の方法ですか、それとも単一のクラスに複数の汎用イベント ハンドラーを実装するために使用できる他の Scala コンストラクトがあるのでしょうか (つまり、ケース クラス、マニフェスト、またはその他の派手なコンストラクトを使用します)。

4

2 に答える 2

11

1 つのクラスでそれを行う方法はわかりません ( 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

2 つの別々のhandle方法の利点は何ですか?

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