用不同的泛型类型实现同一个泛型Java接口的多个实例? [英] Implementing multiple instances of the same generic Java interface with different generic types?

查看:246
本文介绍了用不同的泛型类型实现同一个泛型Java接口的多个实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设计一个事件驱动的系统,并且遇到了一些关于泛型的基本API问题。



我喜欢所有事件来扩展 BaseEvent

  // Groovy伪代码
抽象BaseEvent {
发生日期在

BaseEvent(){
super()

this.occurredOn = new Date()// Now
}
}

我希望所有事件侦听器都能实现一些基本的接口:

  interface EventListener< EVENT extends BaseEvent> {
void onEvent(EVENT event)
}

  class FizzEvent extends BaseEvent {...} 
$ b简单的侦听器,只处理单一类型的事件$ b class FizzEventListener实现EventListener< FizzEvent> {
@Override
void onEvent(FizzEvent fizzEvent){
...
}
}

但是我会有一些侦听器需要处理多种类型的事件:

  
//然后,理想情况下:$ b $ class ComplexListener实现EventListener< FizzEvent> ;,
EventListener< BuzzEvent> {
@Override
void onEvent(FizzEvent fizzEvent){
...
}

@Override
void onEvent(BuzzEvent buzzEvent) {
...
}
}

编译器错误:
$ b


名称冲突:类型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 仍然是 的类型参数,这会导致歧义并且不起作用。



如果未使用扩展关键字,则只会看到 Object 代替,但仍会遇到同样的问题。



这与使用 Type Reification 的C#形成鲜明对比实现泛型并且可以知道换句话说,如果你问Java是否是 List< Dog> 是相同类型的列表作为 List< Car> ,Java会说是,因为它在运行时并不知道更好,而C#会说不保留类型信息。


任何想法解决方案用于处理多个事件?

如果您想使用相同的侦听器接口(例如, onDogBarkEvent(Dog d) onCatMeowEvent(Cat c)或者为不同类型的事件创建单独的侦听器接口 DogBarkListener CatMeowListener )。



在一些Java选项的正确方向。



除此之外,如果您真的对自己的选择感到强烈也可以自由选择您的编程语言,那么你可以考虑让C#做一个旋转,看看它是否更适合你。


I am designing an event-driven system and am running into some basic API problems regarding generics.

I woud like all events to extend BaseEvent:

// Groovy pseudo-code
abstract BaseEvent {
    Date occurredOn

    BaseEvent() {
        super()

        this.occurredOn = new Date() // Now
    }
}

And I would like all event listeners to implement some basal interface:

interface EventListener<EVENT extends BaseEvent> {
    void onEvent(EVENT event)
}

So this works great for simple listeners that only handle a single type of event:

class FizzEvent extends BaseEvent { ... }

class FizzEventListener implements EventListener<FizzEvent> {
    @Override
    void onEvent(FizzEvent fizzEvent) {
        ...
    }
}

But I will have some listeners that need to handle multiple types of events:

class BuzzEvent extends BaseEvent { ... }

// So then, ideally:
class ComplexListener implements EventListener<FizzEvent>,
        EventListener<BuzzEvent> {
    @Override
    void onEvent(FizzEvent fizzEvent) {
        ...
    }

    @Override
    void onEvent(BuzzEvent buzzEvent) {
        ...
    }
}

But this produces compiler errors:

Name clash: The method onEvent(EVENT) of type EventListener has the same erasure as onEvent(EVENT) of type EventListener but does not override it

Any ideas what the solution is for handling multiple events?

解决方案

The problem you're running into is called Type Erasure, which is how Java implements generics. This means that, for Java, the following lines of code:

@Override
void onEvent(FizzEvent fizzEvent) {
    ...
}

@Override
void onEvent(BuzzEvent buzzEvent) {
    ...
}

really look like this:

@Override
void onEvent(BaseEvent fizzEvent) {
    ...
}

@Override
void onEvent(BaseEvent buzzEvent) {
    ...
}

Notice that the type information has been 'erased' and only the super type BaseEvent remains as the type parameter for both methods, which causes ambiguity and won't work.

If the extends keyword had not been used, it would only see Object instead, but would still run into the same problem.

This is in contrast to C#, which uses Type Reification to implement generics and can know the difference of types at runtime.

In other words, if you ask Java whether a List<Dog> is the same kind of list as a List<Car>, Java would say "yes" because it doesn't know any better at runtime, while C# would say "no" because it retains type information.

Any ideas what the solution is for handling multiple events?

You will need to use different method names or signatures if you want to use the same listener interface (e.g. onDogBarkEvent(Dog d), onCatMeowEvent(Cat c) or perhaps create separate listener interfaces for different kinds of events (e.g. DogBarkListener, CatMeowListener).

This should point you in the right direction with a few Java options.

That aside, if you really feel strongly about your choice and are also free to choose your programming language, then you could consider taking C# for a spin and see if it works better for you.

这篇关于用不同的泛型类型实现同一个泛型Java接口的多个实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆