在Java中实现通用接口

问题描述:

我有一个Java泛型问题,我希望有人可以回答。请看下面的代码:在Java中实现通用接口

public interface Event{} 
public class AddressChanged implements Event{} 
public class AddressDiscarded implements Event{} 

public interface Handles<T extends Event>{ 
    public void handle(T event); 
} 

我想实现这个手柄接口是这样的:

public class AddressHandler implements Handles<AddressChanged>, Handles<AddressDiscarded>{ 
    public void handle(AddressChanged e){} 
    public void handle(AddressDiscarded e){} 
} 

但Java不允许使用通用实施手柄的两倍。我可以用C#来完成这项工作,但是如果不使用Reflection或instanceof和casting,则无法在java中找到解决方法。

有没有在java中使用两个通用接口来实现Handles接口的方法?或者也许另一种方式来编写句柄接口,以便最终结果可以完成?

你不能用Java来做到这一点。您只能实现同一个通用接口的一个具体实现。我会做这个:

public class AddressHandler implements Handles<Event>{ 
    public void handle(Event e){ 
     if(e instanceof AddressDiscarded){ 
     handleDiscarded(e); 
     } else if(e instanceof AddressChanged){ 
     handleChanged(e); 
     } 
    } 
    public void handleDiscarded(AddressDiscarded e){} 
    public void handleChanged(AddressChanged e){} 
} 
+4

这是值得商榷的。这“的instanceof级联”是一个非常程序paragidm。当然,它的作品,但恕我直言,它不是很好的风格。但是,因此拥有不同的方法名称可能并不完美,这可能是品味的问题。 – 2010-12-01 15:43:17

+1

这是我会做的。你不必:) – 2010-12-01 15:44:41

+0

-1:你可以在Java中实现多个接口。 – 2010-12-01 15:45:40

AFAIK你不能做到这一点,因为在Java编译源代码时,这些都将归结为handle(Event),使得该方法不明确。

通用信息在Java运行时不可用,与C#不同。这就是为什么它如你所描述的那样工作。

您必须更改方法名称才能使它们具有唯一性,如handleAddressChangedhandleAddressDiscarded

这确实是Java泛型的一个弱点。

不,因为Java中不同的“具体”泛型类型编译为相同类型。你的对象将实现实际的接口是:

public interface Handles { 
    public void handle(Event event); 
} 

而且,很明显,你不能有相同的签名两种不同的方法......

@Amir Raminfar后去,你可以使用visitor模式

interface Event{ 
void accept(Visitor v); 
} 
interface Visitor { 
void visitAddressChanged(AddressChanged a); 
void visitAddressDiscarded(AddressDiscarded a); 
} 

class AddressChanged implements Event{ 
@Override 
public void accept(Visitor v) { 
    v.visitAddressChanged(this); 
} 
} 

class AddressDiscarded implements Event{ 
@Override 
public void accept(Visitor v) { 
    v.visitAddressDiscarded(this); 
} 
} 

class AddressHandler implements Visitor { 
    void handle(Event e){ 
     e.accept(this); 
    } 
    public void visitAddressChanged(AddressChanged e){} 
    public void visitAddressDiscarded(AddressDiscarded e){} 
} 

不幸的不是。通常的解决方案(胖,丑,快)是创建一个界面(即HandlesAddressChange,HandlesAddressDiscarded),并给他们每个人一个不同的方法(handleAddressChange(...), handleAddressDiscarded())。

这样,Java运行时可以将它们分开。

或者您可以使用匿名类。

这是不允许的,因为Java在编译期间擦除通用签名。界面方法实际上会有签名

public void handle(Object event); 

所以你有两种选择。无论是执行不同的处理器为不同的事件:

public class AddressChangedHandler implements Handles<AddressChanged>{ /* ... */ } 
public class AddressDiscardedHandler implements Handles<AddressDiscarded>{ /* ... */ } 

或实现一个处理程序为所有,但检查传入事件的类型:

public void handle(Event e){ 
    if (e instanceof AddressChanged) { 
    handleAdressChanged(e); 
    } 
    else if (e instanceof AddressDiscareded) { 
    handleAdressDiscarded(e); 
    } 
} 

像这样的实现不会因工作的制约因素java规范。 但是,如果你不害怕使用AOP或某种IOC容器,那么可以使用注释。与您的Aspects或容器相比,您可以管理消息传递基础结构并调用您注解的方法。

首先,您必须创建注释。

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface EventConsumer {} 

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface Handles{} 

的可能注释类这样的:

@EventConsumer 
public class AddressHandler{ 
    @Handles 
    public void handle(AddressChanged e){} 
    @Handles 
    public void handle(AddressDiscarded e){} 
}