在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){}
}
AFAIK你不能做到这一点,因为在Java编译源代码时,这些都将归结为handle(Event)
,使得该方法不明确。
通用信息在Java运行时不可用,与C#不同。这就是为什么它如你所描述的那样工作。
您必须更改方法名称才能使它们具有唯一性,如handleAddressChanged
和handleAddressDiscarded
。
这确实是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){}
}
这是值得商榷的。这“的instanceof级联”是一个非常程序paragidm。当然,它的作品,但恕我直言,它不是很好的风格。但是,因此拥有不同的方法名称可能并不完美,这可能是品味的问题。 – 2010-12-01 15:43:17
这是我会做的。你不必:) – 2010-12-01 15:44:41
-1:你可以在Java中实现多个接口。 – 2010-12-01 15:45:40