Implementing a generic interface with a raw type
I have a generic tree, the generic parameter is the data type stored by the nodes:
class TreeNode<D>{
public D data;
.....
}
Then a visitor interface to use along with a tree transversal:
interface Visitor<D> {
void visit(TreeNode<D> node);
}
Some visitors can take advantage of generics:
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;
}
But others don't, they would fit better in a raw class
class NodeCounter implements Visitor {
private int nodeCount = 0;
public void visit(TreeNode node) {
nodeCount++;
}
public int count() {
return nodeCount;
}
But I don't know how implement this last case, the code above don't compile as I have to implement the generic interface not the raw one. I tried implementing
Visitor<?>
with the same result. So my que开发者_Go百科stion is, I'm forced to use a generic type
NodeCounter<D>
to implement the Visitor interface?.
Thanks.
the code above don't compile
I tried compiling your example, and it works fine. I'm using Java 6. What was the compilation error you got?
This is what I successfully compiled:
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;
}
}
Java generics are very powerful, and raw types should almost never be necessary.
You probably want to put some wildcards in. For instance, a visitor may need not know the exact generic argument of the TreeNode
s it is visiting:
interface TreeNodeVisitor<D> {
void visit(TreeNode<? extends D> node);
}
Perhaps better(?), a TreeNode
may not need to know the exact type of visitor.
interface TreeNode<D> {
void accept(TreeNodeVisitor<? super D> visitor);
}
In short - yes, you do need to give the generic interface a type argument.
What you probably should do, is implemenet a non-generic (and possibly empty) interface ITreeNode
, that ITreeNode<D>
inherits from. Any methods that don't need to be generic are declared in this intercace instead. Then, do the same thing for IVisitor
, and NodeCounter
can inherit the non-generic Visitor
interface.
Short schematic:
ITreeNode
ITreeNode<D> implements TreeNode
IVisitor
IVisitor<D> implements IVisitor
NodeCounter implements IVisitor
(Note: I used the C# convention to prefix interfaces with I. NodeCounter
is meant to be a class, while the others are interfaces...)
Java Generics are explicitly designed to be interoperable with raw types using a technique known as Erasure.
So the situation you are describing is directly supported and should compile fine:
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;
}
}
精彩评论