Reputation: 4376
So I'll spare you the giant blocks of code and cut to the chase. I have two classes: one a base "AbstractNode" class and the other a "TokenRingNode" class. The signature for AbstractNode is this:
public abstract class AbstractNode <E extends NetworkEvent>
Then the signature for TokenRingNode:
public class TokenRingNode extends AbstractNode<TokenRingEvent>
I have a method in AbstractNode that is:
public abstract void createEvent(AbstractNode<E> destinationNode);
I have also tried:
public abstract <N extends AbstractNode<E>> createEvent (N destinationNode)
Then in TokenRingNode, I override this abstract method with:
public void createEvent(TokenRingNode destinationNode) { ... }
The problem is, the compiler does not believe that this is a valid override and I am not exactly sure why. TokenRingNode extends Abstract, so can someone illustrate to me why this method is not a valid override?
Upvotes: 1
Views: 130
Reputation: 4572
AbstractNode<TokenRingEvent>
is not necessarily a TokenRingNode
therefore you can’t override
public abstract void createEvent(AbstractNode<TokenRingEvent> destinationNode);
with
public void createEvent(TokenRingNode destinationNode);
It's not related to generics / type erasures, the signature is just different. A AbstractNode<TokenRingEvent> destinationNode
is not a TokenRingMode
(but the opposite, yes).
Upvotes: 0
Reputation: 9941
You can try to define two generics for this in AbstractNode:
public abstract class AbstractNode <E extends NetworkEvent, A extends AbstractNode>
...
public abstract void createEvent(A destinationNode);
and then subclass it as
public class TokenRingNode extends AbstractNode<TokenRingEvent, TokenRingNode>
Upvotes: 2
Reputation: 8874
You need to add one more generic type to AbstractNode, because the event and the destination node can have two different types:
public abstract class AbstractNode <E extends NetworkEvent, N extends AbstractNode<E, N>>
{
public abstract void createEvent(N destinationNode);
}
and then this will compile:
public class TokenRingNode extends AbstractNode<TokenEvent, TokenRingNode>
{
public void createEvent(TokenRingNode destinationNode){
}
}
You cannot do just
public abstract <N extends AbstractNode<E>> createEvent (N destinationNode)
because then you declare the createEvent method to accept ANY AbstractNode<E extends NetworkEvent> as a parameter. But you want it to accept only the TokenRingEvent, and that's why you need to push the type declaration one level higher.
Upvotes: 1
Reputation: 20760
The problem is that the superclass contract promises it accepts AbstractNode<E>
as a parameter, however, you expect a TokenRingNode
specifically , which is only of of the classes that (so a subclass of what it promises to accept. Hence your subclass is accepting less classes than the superclass contract promises.
Upvotes: 1
Reputation: 43159
It's not a valid override, but not because of generics.
If you have an AbstractNode
, it's reasonable to expect that you should be able to call createEvent()
on it with another AbstractNode
as a parameter. But you never define this method on TokenRingNode
.
e.g. ignoring generics for the moment:
AbstractNode n1 = new TokenRingNode();
AbstractNode n2 = new TokenRingNode();
n1.createEvent(n2); // this should work by the contract of AbstractNode, but you never define it
Upvotes: 3