绕过Scala类型擦除(使用Guava EventBus)

时间:2012-12-27 21:49:57

标签: scala event-handling guava

我在Scala项目中使用了Guava的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中不可能以这种方式对不同类型的Guava事件使用相同的Event对象,并且在Scala中是不可能的。但是,Scala证明有许多很好的方法来规避Java的擦除问题。有没有人看到另一种方法来实现这一点,也许使用一些Scala魔法?

1 个答案:

答案 0 :(得分:4)

问题在于Guava:它无法看到类型参数,因此它不会区分这两种方法。唯一可行的解​​决方案是为每种类型创建一个新类。

这真的很容易:

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

然后只要您需要在代码中执行任何操作,只需使用MyEvent[Int]即可。但是番石榴至少需要这么多样板。

请注意,我已使MyEvent[T]构造函数受到保护,因此您必须实例化一个去泛化的类。我不确定这是否适用于您的用例;我会假设的。你也可以绕过它(使用类型类),但它增加了更多的样板。