jcampos8782
jcampos8782

Reputation: 4376

Generic Confusion on Inheritence -- Java

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

Answers (5)

Jerome
Jerome

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

Angelo Fuchs
Angelo Fuchs

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

Jakub Zaverka
Jakub Zaverka

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

Thirler
Thirler

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

Simon Nickerson
Simon Nickerson

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

Related Questions