我有一个接口Node询问方法:
public HashSet getNeighbour();
NodeVariable实现了Node,它的邻居是NodeFunction类型(也实现了Node),我编写了方法:
public HashSet<NodeFunction> getNeighbour();
(在NodeFunction类中反之亦然)。
我发现如果我将Node中方法的签名更改为:
public HashSet<Node> getNeighbour();
然后在NodeVariable和NodeFunction中的方法我得到错误:
factorgraph.NodeFunction中的错误getNeighbour()无法在factorgraph.Node中实现getNeighbour()返回类型java.util.HashSet与java.util.HashSet NodeFunction.java不兼容
这不是很清楚。
我找到了:
Overriding return type in extended interface - Bad idea?
和
现在我在:
中更改了Node方法签名 public HashSet<? extends Node> getNeighbour();
因此编译器停止抱怨。
是不是?为什么HashSet不被视为HashSet的“扩展”?
答案 0 :(得分:1)
首先,根据其他接口而不是具体实现来定义接口中的方法更好。我想说的是getNeighbour()
方法应该是:
public Set getNeighbour();
既然我们知道它只能返回Nodes(或Node的子类型),我们也可以这样定义它:
public Set<? extends Node> getNeighbour();
答案 1 :(得分:0)
HashSet<Node>
实现/子类HashSet<NodeFunction>
, NodeFunction
和Node
也不兼容。同样,List<Number>
和List<Integer>
都不是。 Integer
子类Number
。
static List<Number> getNumberList(int size) {
//ArrayList<Integer> numList = null; //Doesn't compile
ArrayList<Number> numList = null; //Compiles
return numList;
}
如果编译器允许你尝试做什么,那么我可以执行以下操作并抛出ClassCastException
,这就是创建泛型的确切原因。
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() {}
}
除了public Set<NodeFunction> getNeighbour(){}
之外,所有内容在语义/语法上都是有效的。 Java教程涵盖了this问题。