2012-12-27 73 views
1

我在我的Scala項目中使用Guava的EventBus繞過Scala類型擦除(帶番石榴EventBus)

我有一個參數化的事件,像這樣:

class MyEvent[T] 

和一個簡單的事件監聽器:

class MyEventListener { 

    @Subscribe 
    def onStringEvent(event: MyEvent[String]) { 
     println("String event caught") 
    } 

    @Subscribe 
    def onIntEvent(event: MyEvent[Int]) { 
     println("Int event caught") 
    } 

} 

我可以創建com.google.common.eventbus.EventBus,註冊MyEventListener,並觸發一個事件:

val eventBus = new EventBus 
eventBus.register(new MyEventListener) 
eventBus.post(new MyEvent[String]) 

但是,正如您可能已經猜到的那樣,onStringEventonIntEvent作爲結果被調用。問題在於,Java的/ Scala的類型擦除在運行時會脫離參數類型,並且這兩個訂閱在Guava中都顯示爲event: MyEvent

好吧,我的問題:

由於擦除,使用相同的事件對象的不同類型以這種方式番石榴事件不會在Java中是可能的和不可能在Scala中。但是,Scala證明有很多好方法來規避Java的擦除問題。有沒有人看到另一種方式來實現這一點,也許使用一些Scala巫術?

回答

4

問題在番石榴:它看不到類型參數,所以它不會區分這兩種方法。唯一可能的解決方案是爲每種類型創建一個新類。

那可真方便:

class MyEvent[T] protected() { /* Your methods here */ } 
class MyEventInt extends MyEvent[Int] {} 
class MyEventString extends MyEvent[String] {} 

,然後,當您需要做任何事情在你的代碼,只需使用MyEvent[Int]。但番石榴至少需要這麼多的樣板。

請注意,我已對MyEvent[T]構造函數進行了保護,因此您必須實例化一個de-generified類。我不確定這是否適合您的使用案例;我會這樣認爲的。你也可以繞過(使用類型類),但它增加了更多的樣板。

+0

我想你可以使用implicits/typeclasses來刪除一些語法。 –

+0

@ DominicBou-Samra - 如果你有一個例子,你可以自由發表一個例子。對於基本情況 - 實例化MyEventString'沒關係 - 我不知道有什麼方法可以進一步減少樣板。我已經提出了泛型實例化的類型類(但是不可避免地增加了另一個樣板AFAICT)。 –