我正在设计一个事件驱动的系统,并且遇到了有关泛型的一些基本API问题。
我希望所有事件能够扩展BaseEvent
:
// Groovy pseudo-code
abstract BaseEvent {
Date occurredOn
BaseEvent() {
super()
this.occurredOn = new Date() // Now
}
}
我希望所有事件侦听器都实现一些基本接口:
interface EventListener<EVENT extends BaseEvent> {
void onEvent(EVENT event)
}
因此,这对于仅处理单一事件类型的简单侦听器非常有用:
class FizzEvent extends BaseEvent { ... }
class FizzEventListener implements EventListener<FizzEvent> {
@Override
void onEvent(FizzEvent fizzEvent) {
...
}
}
但是我将需要一些侦听器来处理多种类型的事件:
class BuzzEvent extends BaseEvent { ... }
// So then, ideally:
class ComplexListener implements EventListener<FizzEvent>,
EventListener<BuzzEvent> {
@Override
void onEvent(FizzEvent fizzEvent) {
...
}
@Override
void onEvent(BuzzEvent buzzEvent) {
...
}
}
但这会产生编译器错误:
名称冲突:EventListener类型的onEvent(EVENT)方法具有与EventListener类型的onEvent(EVENT)相同的擦除,但不会覆盖它
有什么想法可以解决多个事件吗?
您遇到的问题称为Type Erasure,这是Java实现泛型的方式。这意味着,对于Java,以下代码行:
@Override
void onEvent(FizzEvent fizzEvent) {
...
}
@Override
void onEvent(BuzzEvent buzzEvent) {
...
}
看起来真的像这样:
@Override
void onEvent(BaseEvent fizzEvent) {
...
}
@Override
void onEvent(BaseEvent buzzEvent) {
...
}
请注意,类型信息已被“擦除”,并且只有超级类型BaseEvent
保留为这两种方法的类型参数,这会导致歧义且无法正常工作。
如果extends
未使用关键字,则只能看到该关键字Object
,但仍然会遇到相同的问题。
这与C#相反,C#使用Type Reification实现泛型并且可以在运行时知道类型的差异。
换句话说,如果您问JavaList<Dog>
列表是否与a相同List<Car>
,那么Java会说“是”,因为它在运行时并不了解,而C#会说“否”,因为它保留了类型信息。
有什么想法可以解决多个事件吗?
您将需要使用不同的方法名称或签名,如果你想使用相同的监听器接口(例如onDogBarkEvent(Dog d)
,onCatMeowEvent(Cat c)
或者是创造不同类型的事件(例如单独的侦听器接口DogBarkListener
,CatMeowListener
)。
这应该通过一些Java选项为您指明正确的方向。
这且不说,如果你真的感到强烈的您的选择,并也可以自由选择自己的编程语言,那么你可以考虑采取C#兜风,看看它是否工作更好地为您。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句