Перегрузка универсальных обработчиков событий в Scala - PullRequest
7 голосов
/ 21 декабря 2011

Если я определю следующий общий обработчик событий

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, которую я могу использовать, чтобы заставить один класс реализовывать несколько универсальных обработчиков событий (т. Е. Используя case-классы, манифесты или некоторые другие причудливые конструкции)?

Ответы [ 2 ]

11 голосов
/ 21 декабря 2011

Я не знаю, как сделать это в одном классе (кроме как сделать Event ADT и определить дескриптор для принятия параметра типа 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)
  ...
}
4 голосов
/ 20 января 2012

В чем преимущество двух отдельных handle методов?

def handle(rawEvent: Event) = rawEvent match {
  case e: InventoryItemCreated => ...
  case e: InventoryItemDeactivated => ...
}
...