代码之家  ›  专栏  ›  技术社区  ›  Carl

Java迭代器/可迭代子接口

  •  4
  • Carl  · 技术社区  · 17 年前

    我有一个用于各种类的接口,所有这些类都应该实现迭代器,所以我有类似的

    public interface A extends Iterable<A> { ...otherMethods()... }
    

    但是,对于具体的类,这意味着我必须使用

    public class B implements A { public Iterator<A> iterator() {...} }
    

    当我想(或者至少想)使用 public Iterator<B> iterator() {...} 因此,类的具体使用可以具有显式类型(在我希望接口中没有的方法可用的情况下,或者类似的方法)。也许这永远不会出现?或者它的设计太差了?

    另一方面,使用迭代器接口

    public interface A extends Iterator<A> { ...otherMethods()... }
    

    具体的类可以用

    public class B implements A { public B next() {...} }
    

    给出了什么?

    5 回复  |  直到 17 年前
        1
  •  1
  •   Yishai    17 年前

    因为B扩展了A,所以具体类编译得很好,因为Java 5在子类上返回类型可以是超类上返回类型的子类。

    至于通用的,我已经碰到了同一面墙,而你有两个我知道的选项。

    一种是对a进行参数化:

     public interface A<T extends A> extends Iterable<T>
    

    然后:

    public class B implements A<B>
    

    但是,这有一个缺点,即您需要给定的参数为,而不是将其固定,即使您需要:

    private class NoOneSees implements A<A>
    

    关于你是否真的想要 Iterator<B> ,对于iterable,最好是这样,并且考虑到这些是接口,重新声明参数的需求可能是合理的。如果您开始继承具体的类,以及那些除了可迭代之外有意义的东西(在这里您可能需要协方差),它会变得更复杂一些。例如:

    public interface Blah<T> {
        void blah(T param);
    }
    
    public class Super implements Blah<Super> {
        public void blah(Super param) {}
    }
    
    public class Sub extends Super {
        public void blah(Super param) {}
       //Here you have to go with Super because Super is not paramaterized
       //to allow a Sub here and still be overriding the method.
    }
    

    同样,对于协方差,不能声明类型为的变量 Iterator<A> 然后分配一个 迭代器<b> 其中,即使b扩展了a。

    另一个选择是活的事实是,进一步的实现/子类仍将引用a。

        2
  •  2
  •   Matt    17 年前

    卡尔是对的,我的第一个答案没有汇编出来,但似乎是这样。不确定你到底想要什么。

    public interface A<T extends A> extends Iterable<T> {
    
    }
    
    public class B implements A<B> {
    
        @Override
        public Iterator<B> iterator() {
            return null;
        }
    
        3
  •  1
  •   Andrzej Doyle    17 年前

    其他答案有正确的要点,但是通过将泛型类型声明为

    A<T extends A<T>>
    

    这将强制类返回其自身类型或更低类型的迭代器,因此您可以声明

    class B implements A<B>
    

    但不是

    class B implements A<A>
    

    我怀疑这更接近于您想要的(即实现必须返回迭代器,而不是简单地返回迭代器) A s)。

    注意你的经历 Iterator VS Iterable 源于缺乏泛型类型的协方差; B 一个 但是 Iterator<B> 一个 Iterator<A> .

        4
  •  0
  •   Kutzi    17 年前

    我想这就是你想要的:

    public interface A<T extends A<?>>  extends Iterable<T>
    
    public class B implements A<B> {
      public Iterator<B> iterator() {...}
    }
    
        5
  •  0
  •   DJClayworth    17 年前

    您的设计决策是您自己的,但我想不出任何理由让设计中的每个类实现它。集合中必须包含某种东西,但实际上不是集合本身。我会仔细研究一下基本设计。也许有些iterables想要返回与自身无关的事物的迭代器。