2011-12-20 3 views
7

나는 각에 대한 이벤트 핸들러를 구현하는 하나의 클래스를 만들 어떻게이오버로딩 일반적인 이벤트 핸들러

trait Event { 

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

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

같은 이벤트 유형의 다음과 같은 일반적인 이벤트 핸들러

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

을 정의하는 경우 이 사건들 중? 나는 시도했다 :

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

    } 

    def handle(event: InventoryItemDeactivated) = { 

    } 
    } 

그러나 스칼라는 형질이 두 번 상속 될 수 없다고 불평한다.

해결책을 암시하는 answer이 발견되었지만 여러 클래스 (각 처리기마다 하나씩)가 필요합니다. 이 방법이 정말로 유일한가요? 아니면 하나의 클래스가 여러 일반 이벤트 처리기 (예 : 사례 클래스, 매니페스트 또는 기타 멋진 구성 요소 사용)를 구현하는 데 사용할 수있는 다른 Scala 구문이 있습니까?

답변

11

Event을 ADT로 만들고 Event 매개 변수를 허용하도록 핸들을 정의하는 것을 제외하고는 한 클래스에서이 방법을 알지 못합니다. 그렇다고해도 보이는 종류의 typesafety는 제거 될 것입니다. 에 대한).

대신 유형 클래스 패턴을 사용하는 것이 좋습니다.

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

두 개의 개별 handle 방법의 장점은 무엇입니까?

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