代码之家  ›  专栏  ›  技术社区  ›  Vivin Paliath

涉及实现接口的实现问题

  •  4
  • Vivin Paliath  · 技术社区  · 15 年前

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

    我有一个 Node<T> AbstractNode<T> 实现 Node GenericNode<T> (可以有0到 n -(二叉树)类 抽象节点<T> . 这部分很简单。

    接下来,我创建了一个 Tree<T> AbstractTree<T> 实现 树<T> 接口。从那以后,我开始写一篇文章 GenericTree<T> 扩展的类 树<T> . 这就是我开始有问题的地方。

    常规树<T> GenericTreeNode<T> . 这包括根。在我的 树<T> 我拥有的接口:

    public interface Tree<T> {
    
        void setRoot(Node<T> root);
    
        Node<T> getRoot();
    
        List<Node<T>> postOrder();
    
        ... rest omitted ...
    }
    

    而且, 抽象树<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 ...
    }
    

    常规树<T>

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

    但这意味着您可以使用 节点<T> . 也可以将树的根设置为树的任何子类型 . 我希望能够将节点的类型限制为它可以表示的树的类型。要解决这个问题,我可以这样做:

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

    然而, setRoot 仍然接受类型为的参数 节点<T>

    • 做一个 instanceof 它将检查限制为运行时。我不太喜欢这个。
    • 删除 并让基类实现这个方法。这意味着它不是契约的一部分,任何想要创建新类型树的人都需要记住实现这个方法。

    我的第二个问题是关于 postOrder 哪个是 List<Node<T>> 常规树<T> 对象和调用 邮购 节点<T> 物体。这意味着在遍历(使用foreach构造)时,它们必须执行显式强制转换 常规节点<T> 节点<T> . 然而,这再次将其从契约中删除,任何想要创建新类型树的人都必须记住实现此方法。有更好的办法吗?

    1 回复  |  直到 15 年前
        1
  •  4
  •   Alexander Pogrebnyak    15 年前

    我认为你是本末倒置。

    Tree<T> Node<T> . 只有在那之后,分析他们有什么共同的实现,只有在那之后,实现你的 Abstract 如果它们在那一点上仍然有意义的话。

    回答第二个问题:

    如果简单的话 节点<T> 不会把它切到你的肚子里 Tree 接口,则您别无选择,只能向泛型接口声明第二个参数并在其上设置边界,如下所示

    public interface Tree<
      T,
      TNode extends Node< T >
    >
    {
    
        void setRoot(TNode root);
    
        TNode getRoot();
    
        List<TNode> postOrder();
    
        ... rest omitted ...
    }
    

    然后是抽象树

    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 ( )
      {
        ...
      }
      ...
    }