关于继承的一般困惑 - Java

时间:2012-04-13 08:17:15

标签: java generics

因此,我将为您节省大量代码并切入追逐。我有两个类:一个是基本的“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,所以有人可以向我说明为什么这个方法不是有效的覆盖?

5 个答案:

答案 0 :(得分:3)

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

如果您有AbstractNode,那么您可以使用其他createEvent()作为参数调用AbstractNode,这是合理的。但是你永远不会在TokenRingNode上定义这个方法。

e.g。暂时忽略了泛型:

AbstractNode n1 = new TokenRingNode();
AbstractNode n2 = new TokenRingNode();
n1.createEvent(n2); // this should work by the contract of AbstractNode, but you never define it

答案 1 :(得分: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>

答案 2 :(得分:1)

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

答案 3 :(得分: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方法接受任何AbstractNode&lt; E extends NetworkEvent&gt;作为参数。但是你希望它只接受TokenRingEvent,这就是你需要将类型声明推高一级的原因。

答案 4 :(得分:0)

AbstractNode<TokenRingEvent>不一定是TokenRingNode,因此您无法覆盖

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

public void createEvent(TokenRingNode destinationNode); 

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