2011-12-20 14 views
7

Se io definisco il seguente gestore di evento genericoOverloading gestori di eventi generici a Scala

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

con il tipo di evento come questo

trait Event { 

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

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

come faccio poi fare una sola classe che implementa i gestori di eventi per ogni di questi eventi? Ho provato:

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

    } 

    def handle(event: InventoryItemDeactivated) = { 

    } 
    } 

ma Scala si lamenta che un tratto non può essere ereditato due volte.

Ho trovato questo answer che suggerisce una soluzione, ma richiede più classi (una per ogni gestore). È davvero questo l'unico modo o c'è qualche altro costrutto di Scala che posso usare per fare in modo che una singola classe implementa più gestori di eventi generici (cioè usando classi di casi, manifesti o qualche altro costrutto di fantasia)?

risposta

11

Non conosco un modo per farlo in una classe (tranne rendendo Event un ADT e definendo l'handle per accettare un parametro di tipo Event. Ma ciò toglierebbe il tipo di typesafety che sembra essere in cerca per).

Suggerirei invece di utilizzare un modello di classe tipo.

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

Qual è il vantaggio di due handle metodi separati?

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