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

继承+接口问题

  •  1
  • Carl  · 技术社区  · 16 年前

    我有一个接口来描述类何时可以创建自己的“下一个”版本:

    public interface Prototypeable<Type extends Prototypeable<Type>> {
     public Type basePrototype(); // the zeroth raw instance of Type
     public Type nextPrototype(); // the next instance of Type
    }
    

    与…一起使用

    public class Prototyper {
     public static <Type extends Prototypeable<Type>> List<Type> prototypeFactor(int numberOfInstances, Type proto) {
      List<Type> result = new ArrayList<Type>(numberOfInstances);
      Type holder = proto.basePrototype();
      result.add(holder);
      for (int i=1; i<numberOfInstances;i++) result.add(holder = holder.nextPrototype());
      return result;
    }
    

    A implements Prototypeable<A> ,以及一个子类 AButMore extends A AButMore extends A implements Prototypeable<AButMore> A AButMore 两者都实现了一些其他接口,并且实现与 .

    • 伪装饰两个类-即,有一个基类不实现 Prototypeable 接口,从该接口继承到适当的子类,然后将两个类都扩展到它们自己的原型版本。不利的一面似乎是课程繁多。

    • A 而不是建造 阿布特莫尔 A 和委派所有复制的方法。然而,在我看来,委托代码总是很愚蠢,尤其是当可以继承的每个方法都将被委托而不做任何修改时。

    • 原型化 指定 Object 作为返回类型,并让工厂 Class 铸造参数。这里的缺点是,如果使用不当,这可能会导致不安全的强制转换。

    编辑 :澄清:目的是制造具有某种顺序依赖性的实例,而不具有类变量。最简单的例子是,如果它们都有一个索引变量-basePrototype将提供一个0-index实例,nextPrototype()将提供一个index+1实例(基于从中调用方法的实例的索引)。这个特殊的案例有点简单(可能可以用一种更简单的方式实现),但是它涵盖了这个想法。

    :为了进一步澄清,这里是确切的当前实现(我使用上面的第三种方案):

    public class BuildFromPrototype {
     public static <T extends Prototypeable> List<T> build(int buildCount, Class<T> protoClass, T prototype) {
      if (protoClass==null || prototype==null || buildCount<=0) return null;
      if( protoClass.isInstance(prototype.basePrototype()) && protoClass.isInstance(prototype.nextPrototype()) ) {
       List<T> result = new ArrayList<T>(buildCount);
       T pHolder = protoClass.cast(prototype.basePrototype());
       result.add(pHolder);
       for (int i=1;i<buildCount;i++)
        result.add(pHolder = protoClass.cast(pHolder.nextPrototype()));
       return result;
      } else return null;
     }
    
     public interface Prototypeable {
      public Object nextPrototype();
      public Object basePrototype();
     }
    }
    

    null 是一种选择 Exception 等级 班级。

    2 回复  |  直到 16 年前
        1
  •  1
  •   Steve B.    16 年前

    我不知道你想如何定义“下一个”版本,看起来你想做元类编程,这在java中是做不到的,也就是说,我看不出如何让泛型类型系统管理运行时确定的一系列类型,因为它们在运行时被类型删除并且不存在。一个定义了从一种类型到下一种类型的映射的接口怎么样,例如

    public interface PrototypeMapping<U extends Prototypeable<Type>,V extends U>{
       public V mapTo(U u);
    }
    
        2
  •  0
  •   Andrzej Doyle    16 年前

    在Java的泛型中唯一可以表达的关系是超/子类型关系。对我来说,听起来你并不想要越来越多的特定类(即子类型),而是想要同一接口的“兄弟”实现。您不能仅使用纯泛型类型来表达这一点—您不能对类进行注释,以便Java知道MyImplB是MyImplA的“下一个”实现。

    isInstance 可能不是最有用的限制;编译时检查通常是更好的选择。

    /**
     * @param N the specific class of the next type
     */
    public class/interface Type<N extends Type>
    {
       public Type<?> basePrototype();
       public N nextPrototype();
    }
    
    public class MyImplA implements Type<MyImplB> { ... }
    public class MyImplB implements Type<MyImplC> { ... }
    // ... and so on
    

    这将静态地强制不同类型实现之间的链接。

    不过,我不确定在您所展示的情况下它对您有多大帮助,因为实际上没有太多支持类型安全的异构容器。因为您将所有内容都放在一个ArrayList中,所以您不能断言列表的内容比 Type<?> . 不过,这将有助于处理单个操作。