0

所以,假设我们有一个简单的界面

public interface ICopyable<T> {
    void copyFrom(T original);
}

这基本上添加了一个带有参数化类型的 copyFrom 方法。你有一个扩展它的接口:

public interface ISomeObject<T> extends ICopyable<T> {
    String getType();
}

除了类型之外,该接口当然没有添加任何有价值的东西,但让我们假设其中有一些有用的方法。这个想法还是一样的——这个接口的所有对象都有一个 getType() 方法,它们可以将一个相同类型的对象从一个对象复制到另一个对象。

现在让我们有这个接口的两个实现,第二个实现继承自第一个:

public static class ActualObject1 implements ISomeObject<ActualObject1> {
    Object data1;

    @Override public void copyFrom(final ActualObject1 original) {
        this.data1 = original.data1;
    }

    @Override public String getType() {
        return this.getClass().getSimpleName();
    }
}

public static class ActualObject2 extends ActualObject1 {
    Object data2;

    @Override public void copyFrom(final ActualObject1 original) {
        super.copyFrom(original);
        // oh no! i've just realized that i'm not copying the ActualObject2!
    }
}

所以第二个对象(ActualObject2)应该扩展ActualObject1,但如果这样做,它就不能实现正确的“copyFrom”方法,因为第一个类只为自己实现接口ISomeObject。它显然希望以某种方式允许将 ActualObject2 相互复制。但是怎么做?

它不能只声明实现 ISomeObject ,因为它会与其父级的实现类型发生冲突。所以你会想做类似的事情吗?

public static class ActualObject1<T extends ActualObject1> implements ISomeObject<T> {
    Object data1;

    @Override public void copyFrom(final ActualObject1 original) {
        this.data1 = original.data1;
    }

    @Override public String getType() {
        return this.getClass().getSimpleName();
    }
}

public static class ActualObject2 extends ActualObject1<ActualObject2> {
    Object data2;

    @Override public void copyFrom(final ActualObject2 original) {
        super.copyFrom(original);
        this.data2 = original.data2;
    }
}

基本上参数化class1,class2将自己指定为参数。一切正常,您可以创建两种类型的实例:

ActualObject1 obj1 = new ActualObject1();

但是有一个“小”问题 - obj1 有一个原始类型。完整的声明看起来相当愚蠢:

ActualObject1<ActualObject1> obj2 = new ActualObject1<>();

但它有效。然而,这个类的“原始类型”性质可能会咬人,例如在这个 scanario 中:

public static class SomeOtherParameterizedClass<T extends ISomeObject<T>> {
    void copyObjects(T obj1, T obj2) {
        obj1.copyFrom(obj2);
    }
}

因此,您正在创建一些由 <T extends ISomeObject<T>> 参数化的随机类。理论上你可以这样说:<T extends ISomeObject> 但是你不能安全地在“copyFrom”中使用 T。换句话说 - 这是一个有效的类参数化,它有一点。

但是你不能为 ActualObject1 参数化它:

SomeOtherParameterizedClass<ActualObject1> a1 = new SomeOtherParameterizedClass<>();

是的 - 不起作用。暗示:

SomeOtherParameterizedClass<ActualObject2> a2 = new SomeOtherParameterizedClass<>();

工作得很好...

那么这里的正确方法是什么?我对尽可能地保留类型安全更感兴趣,因为可以肯定你可以一直使用原始类型而不必担心任何事情,但它是为弱者准备的!:-)

我们使用的是静态类型语言,所以这有点像一个学术问题——用泛型设计这个类层次结构的正确方法是什么?是否偶尔需要使用原始类型才能正常工作?

4

0 回答 0