I have an interface Node that asks for the method:
public HashSet getNeighbour();
NodeVariable implements Node, and its neighbours are of type NodeFunction (that implements Node, too), and I wrote the method:
public HashSet<NodeFunction> getNeighbour();
(and viceversa in NodeFunction class).
I found out that if I change the signature of method in Node to:
public HashSet<Node> getNeighbour();
then on the methods in NodeVariable and NodeFunction I get the error:
Error getNeighbour() in factorgraph.NodeFunction cannot implement getNeighbour() in factorgraph.Node return type java.util.HashSet is not compatible with java.util.HashSet NodeFunction.java
This is not really clear.
I found:
Overriding return type in extended interface - Bad idea?
and
and now I changed the Node method signature in:
public HashSet<? extends Node> getNeighbour();
thus the compiler stops complaining.
Is it right? Why HashSet is not considered like an "extension" of HashSet?
HashSet<Node>
and HashSet<NodeFunction>
aren't compatible, even though NodeFunction
implements/subclasses Node
. Similarly, neither are List<Number>
and List<Integer>
. Integer
subclasses Number
.
static List<Number> getNumberList(int size) {
//ArrayList<Integer> numList = null; //Doesn't compile
ArrayList<Number> numList = null; //Compiles
return numList;
}
If the compiler allowed what your trying to do, then I could do the following and a ClassCastException
would be thrown, which is the exact reason generics was created.
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main( String[] args ) {
Node nd = getInstance();
Set<Node> ndSet = nd.getNeighbour();
ndSet.add( new NodeSign() );
nd.removeSingleNeighbor(); //throws ClassCastException
}
static Node getInstance() {
return new NodeVariable();
}
}
interface Node {
public Set<Node> getNeighbour();
public void removeSingleNeighbor();
}
class NodeVariable implements Node {
Set<NodeFunction> ndFuncList = new HashSet<NodeFunction>();
public Set<NodeFunction> getNeighbour(){ return ndFuncList; } //wont' compile
//HERE!!!!
public void removeSingleNeighbor() {
NodeFunction ndFunc = (NodeFunction)ndFuncList.toArray()[ndFuncList.size()-1]; //throws ClassCastException
}
}
class NodeFunction implements Node {
public Set<NodeFunction> getNeighbour(){ return null; } //won't compile
public void removeSingleNeighbor() {}
}
class NodeSign implements Node {
public Set<NodeFunction> getNeighbour(){ return null; } //won't compile
public void removeSingleNeighbor() {}
}
Everything is semantically/syntactically valid except public Set<NodeFunction> getNeighbour(){}
. The Java tutorials cover this issue.