我有一个通用树,泛型参数是节点存储的数据类型:
class TreeNode<D>{
public D data;
.....
}
然后一个访问者界面与树横向一起使用:
interface Visitor<D> {
void visit(TreeNode<D> node);
}
有些访问者可以利用泛型:
class DataListCreator<D> implements Visitor<D> {
List<D> dataList = new ArrayList<D>();
public void visit(TreeNode<D> node) {
dataList.add(node.data);
}
public List<D> getDataList() {
return dataList;
}
但是其他人没有,他们会更适合原始课程
class NodeCounter implements Visitor {
private int nodeCount = 0;
public void visit(TreeNode node) {
nodeCount++;
}
public int count() {
return nodeCount;
}
但我不知道如何实现这最后一种情况,上面的代码不能编译,因为我必须实现 通用接口不是原始接口。我尝试过实施
Visitor<?>
具有相同的结果。所以我的问题是,我被迫使用泛型
NodeCounter<D>
实现访问者界面?。
感谢。
答案 0 :(得分:3)
上面的代码不能编译
我尝试编译你的例子,它工作正常。我正在使用Java 6.你得到的编译错误是什么?
这是我成功编译的内容:
class TreeNode<D>{
public D data;
}
interface Visitor<D> {
void visit(TreeNode<D> node);
}
class NodeCounter implements Visitor {
private int nodeCount = 0;
public void visit(TreeNode node) {
nodeCount++;
}
public int count() {
return nodeCount;
}
}
答案 1 :(得分:3)
Java泛型非常强大,几乎不需要原始类型。
您可能想要放入一些通配符。例如,访问者可能无需知道它正在访问的TreeNode
的确切通用参数:
interface TreeNodeVisitor<D> {
void visit(TreeNode<? extends D> node);
}
或许更好(?),TreeNode
可能不需要知道访问者的确切类型。
interface TreeNode<D> {
void accept(TreeNodeVisitor<? super D> visitor);
}
答案 2 :(得分:1)
简而言之 - 是的,你需要给通用接口一个类型参数。
你可能应该做的是,实现一个非通用的(可能是空的)接口ITreeNode
,ITreeNode<D>
继承自。{1}}。任何不需要是通用的方法都会在此intercace中声明。然后,为IVisitor
执行相同的操作,NodeCounter
可以继承非通用Visitor
接口。
简短示意图:
ITreeNode
ITreeNode<D> implements TreeNode
IVisitor
IVisitor<D> implements IVisitor
NodeCounter implements IVisitor
(注意:我使用C#约定来为I添加前缀。NodeCounter
是一个类,而其他是接口......)
答案 3 :(得分:1)
Java Generics明确设计为使用称为Erasure的技术与原始类型互操作。
所以你所描述的情况是直接支持的,应该编译好:
class TreeNode<D>{
public D data;
}
interface Visitor<D> {
void visit(TreeNode<D> node);
}
class NodeCounter implements Visitor {
private int nodeCount = 0;
public void visit(TreeNode node) {
nodeCount++;
}
public int count() {
return nodeCount;
}
}