2011-12-20 12 views
7

Si defino el siguiente controlador de eventos genéricosSobrecarga de controladores de eventos genéricos en Scala

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

con el tipo de evento como este

trait Event { 

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

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

¿cómo puedo entonces hacer una sola clase que implementa controladores de eventos para cada de estos eventos? Intenté:

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

    } 

    def handle(event: InventoryItemDeactivated) = { 

    } 
    } 

pero Scala se queja de que un rasgo no se puede heredar dos veces.

Encontré este answer que sugiere una solución, pero parece requerir múltiples clases (una para cada controlador). ¿Es esta realmente la única manera o hay alguna otra construcción de Scala que pueda usar para hacer que una sola clase implemente múltiples manejadores de eventos genéricos (es decir, usando clases de casos, manifiestos u otro constructo de fantasía)?

Respuesta

11

No sé de una manera de hacerlo en una clase (excepto al hacer Event un ADT y definir el identificador para aceptar un parámetro del tipo Event. Pero eso quitaría el tipo de seguridad de tipo que parece estar buscando para).

Sugiero usar un patrón tipo-clase en su lugar.

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

¿Cuál es la ventaja de dos métodos distintos handle?

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