具有通用引用的树接口

时间:2013-06-27 14:29:43

标签: java generics interface tree

我遇到了一个我们已经实现的树的问题,这是一个示例:

public interface TreeNode {
    TreeNode getParent();
    void setParent(TreeNode parent);

    List<TreeNode> getChildren();
    void setChildren(List<TreeNode> children);
}

所以,到现在为止这很容易,但是我们有一些树的变体,所以我们有一些这样的接口:

public interface TreeNodeWithX extends TreeNode {
    String getX();
    void setX(String x);
}

public interface TreeNodeWithY extends TreeNode {
    Boolean getY();
    void setY(Boolean y);
}

所以,我需要一个TreeNodeWithX对象(是的,它的实现)从其getParent方法返回一个TreeNodeWithX对象(与TreeNode接口中的其他方法相同)。

来自TreeNodeWithY的相同行为,getParent()应返回TreeNodeWithY。

我尝试过一些泛型方法,例如:

public interface TreeNode<T extends TreeNode> {
    T getParent();
    void setParent(T parent);

    List<T> getChildren();
    void setChildren(List<T> children);
}

但是,在实施方法的某些时候,我总是遇到麻烦。我的问题是,我是否使用我的通用界面正确的方式或我在这里做错了什么?

这种递归泛型引用并没有真正帮助我......

3 个答案:

答案 0 :(得分:6)

您希望您的节点处理通用数据,而不是只生成要保留的通用TreeNode。 IMO你的界面应该使用T来处理数据并保留其他方法:

public interface TreeNode<T> {
    TreeNode<T> getParent();
    void setParent(TreeNode<T> parent);

    List<TreeNode<T>> getChildren();
    void setChildren(List<TreeNode<T>> children);

    T getData();
    void setData(T data);
}

现在,您可以TreeNode<String>TreeNode<Boolean> getData方法将返回StringBoolean(取决于传递的泛型类参数)。

TreeNode<String> treeNode = new SomeImplementationOfTreeNode<String>();
treeNode.setData("Hello world");
System.out.println(treeNode.getData()); // "Hello world"

答案 1 :(得分:4)

TreeNode的类型应该是每个节点上保存的的类型,而不是类型 TreeNode (我们已经知道了)正在处理TreeNodes

试试这个:

/**
 * A Node in a Tree
 * @param <T> The type of the value held at each node
 */
public interface TreeNode<T> {
    TreeNode<T> getParent();
    void setParent(TreeNode<T> parent);

    List<TreeNode<T>> getChildren();
    void setChildren(List<TreeNode<T>> children);

    // A getter/setter of type `T` to the node for the "value" held there.
    T getValue();
    void setValue(T value);
}

考虑省略setter并在实现中创建字段final,将值传递给构造函数:

// Impl if TreeNode doesn't declare a setValue() method
public class MyTreeNode<T> implements TreeNode<T> {
    final T value;
    public MyTreeNode(T value) {
        this.value = value;
    }
    // rest of impl
}

如果您只考虑一个实现,请考虑将TreeNode作为一个类。

答案 2 :(得分:2)

TreeNode<T extends TreeNode>不是正确的做法。如何使用单一界面:

public interface TreeNode<T> {
    TreeNode<T> getParent();
    void setParent(TreeNode<T> parent);

    List<TreeNode<T>> getChildren();
    void setChildren(List<TreeNode<T>> children);

    T getValue();
    void setValue(T x);
}