1

所以我会为你省去巨大的代码块,直奔主题。我有两个类:一个是基础“AbstractNode”类,另一个是“TokenRingNode”类。AbstractNode 的签名是这样的:

public abstract class AbstractNode <E extends NetworkEvent>

然后是 TokenRingNode 的签名:

public class TokenRingNode extends AbstractNode<TokenRingEvent>

我在 AbstractNode 中有一个方法是:

public abstract void createEvent(AbstractNode<E> destinationNode);

我也试过:

public abstract <N extends AbstractNode<E>> createEvent (N destinationNode)

然后在 TokenRingNode 中,我重写了这个抽象方法:

public void createEvent(TokenRingNode destinationNode) { ... } 

问题是,编译器不相信这是一个有效的覆盖,我不确定为什么。TokenRingNode 扩展了 Abstract,所以有人可以向我说明为什么这个方法不是有效的覆盖吗?

4

5 回答 5

3

这不是一个有效的覆盖,但不是因为泛型。

如果您有一个AbstractNode,那么可以合理地期望您应该能够createEvent()使用另一个AbstractNode作为参数来调用它。但是你永远不会在TokenRingNode.

例如暂时忽略泛型:

AbstractNode n1 = new TokenRingNode();
AbstractNode n2 = new TokenRingNode();
n1.createEvent(n2); // this should work by the contract of AbstractNode, but you never define it
于 2012-04-13T08:20:02.457 回答
2

您可以尝试在 AbstractNode 中为此定义两个泛型:

public abstract class AbstractNode <E extends NetworkEvent, A extends AbstractNode>
...
public abstract void createEvent(A destinationNode);

然后将其子类为

public class TokenRingNode extends AbstractNode<TokenRingEvent, TokenRingNode>
于 2012-04-13T08:49:34.287 回答
1

您需要向 AbstractNode 添加一个更通用的类型,因为事件和目标节点可以有两种不同的类型:

public abstract class AbstractNode <E extends NetworkEvent, N extends AbstractNode<E, N>>
{
    public abstract void createEvent(N destinationNode);
}

然后这将编译:

public class TokenRingNode extends AbstractNode<TokenEvent, TokenRingNode>
{
    public void createEvent(TokenRingNode destinationNode){
    }
}

你不能只做

public abstract <N extends AbstractNode<E>> createEvent (N destinationNode)

因为然后您声明 createEvent 方法以接受 ANY AbstractNode<E extends NetworkEvent> 作为参数。但是您希望它只接受 TokenRingEvent,这就是您需要将类型声明推高一级的原因。

于 2012-04-13T08:49:26.170 回答
1

问题是超类合同承诺它接受AbstractNode<E>作为参数,但是,你期望一个TokenRingNode 特别的,它只是那些(所以它承诺接受的子类的子类。因此你的子类接受的类比超类少合同承诺。

于 2012-04-13T08:20:52.173 回答
0

AbstractNode<TokenRingEvent>不一定是 aTokenRingNode因此你不能覆盖

public abstract void createEvent(AbstractNode<TokenRingEvent> destinationNode);

public void createEvent(TokenRingNode destinationNode); 

它与泛型/类型擦除无关,签名只是不同。AAbstractNode<TokenRingEvent> destinationNode不是 a TokenRingMode(但相反,是的)。

于 2012-04-13T08:53:25.850 回答