涉及实现接口的实现问题

时间:2010-05-25 22:19:05

标签: java oop inheritance interface implementation

我正在为不同类型的树编写一组集合类。我这样做是为了学习练习,我也希望它能成为一种有用的东西。我真的想以正确的方式做到这一点,所以我一直在阅读Effective Java,我也一直在研究Joshua Bloch通过查看源代码来实现集合类的方式。我似乎对所做的工作有一个很好的了解,但我还有一些事情需要解决。

我有一个Node<T>接口和一个实现AbstractNode<T>接口的Node类。然后我创建了一个GenericNode<T>(一个可以有0到 n 子节点的节点,它是 n -ary tree)的一部分,它扩展了{{ 1}}并实现AbstractNode<T>。这部分很简单。

接下来,我创建了一个Node<T>接口和一个实现Tree<T>接口的AbstractTree<T>类。之后,我开始编写Tree<T>类,扩展GenericTree<T>并实现AbstractTree<T>。这是我开始遇到问题的地方。

就设计而言,Tree<T>只能由GenericTree<T>类型的节点组成。这包括根。在我的GenericTreeNode<T>界面中,我有:

Tree<T>

并且public interface Tree<T> { void setRoot(Node<T> root); Node<T> getRoot(); List<Node<T>> postOrder(); ... rest omitted ... } 实现了这个接口:

AbstractTree<T>

public abstract class AbstractTree<T> implements Tree<T> { protected Node<T> root; protected AbstractTree() { } protected AbstractTree(Node<T> root) { this.root = root; } public void setRoot(Node<T> root) { this.root = root; } public Node<T> getRoot() { return this.root; } ... rest omitted ... } ,我可以:

GenericTree<T>

但这意味着您可以使用public GenericTree(Node<T> root) { super(root); } 的任何子类型创建通用树。您还可以将树的根设置为Node<T>的任何子类型。我希望能够将节点的类型限制为它可以表示的树的类型。要解决这个问题,我可以这样做:

Node<T>

但是,public GenericTree(GenericNode<T> root) { super(root); } 仍然接受setRoot类型的参数。这意味着用户仍然可以使用错误类型的根节点创建树。如何强制执行此约束?我能想到的唯一方法是:

  • 执行Node<T>将检查限制为运行时。我不是这个的忠实粉丝。
  • 从接口中删除instanceof并让基类实现此方法。这意味着它不是合同的一部分,任何想要制作新类型树的人都需要记住实现这种方法。

有更好的方法吗?

我遇到的第二个问题是setRoot的返回类型postOrder。这意味着,如果用户正在List<Node<T>>对象上操作并调用GenericTree<T>,则他或她会收到包含postOrder个对象的列表。这意味着当迭代(使用foreach构造)时,如果他们想要使用仅在该类中定义的方法,则他们将对Node<T>执行显式强制转换。我不喜欢把这个负担放在用户身上。在这种情况下我有什么选择?我只能考虑从接口中删除该方法,并让子类实现此方法,确保它返回GenericNode<T>的适当子类型的列表。但是,这再一次将它从合同中删除,并且任何想要创建新类型树的人都必须记住实现此方法。还有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

我认为你把马放在马前。

实施Tree<T>Node<T>的几个具体实例。只有在此之后才分析它们共有的实现,并且只有在实现了Abstract类之后才能实现它们。

修改

回答你的第二个问题:

如果简单的Node<T>没有在Tree接口中删除它,那么你别无选择,只能向泛型接口声明第二个参数并在其上加上边界,就像这样

public interface Tree<
  T,
  TNode extends Node< T >
>
{

    void setRoot(TNode root);

    TNode getRoot();

    List<TNode> postOrder();

    ... rest omitted ...
}

然后是AbstractTree

public abstract class AbstractTree<
  T,
  TNode extends Node< T >
> implements Tree<T, TNode> {

  protected TNode root;

  protected AbstractTree(TNode root) {
    this.root = root;
  }

  ...
}

然后是GenericTree

public class GenericTree< T >
  extends AbstractTree< T, GenericNode< T > >
{

  public GenericTree ( GenericNode< T > root )
  {
    super( root );
  }

  @Override
  public List< GenericNode< T > > postOrder ( )
  {
    ...
  }
  ...
}