小编典典

涉及继承的Java泛型

java

我有一个(对我而言)复杂的Java泛型问题。我通读了一些文档,并了解了一些,但不是全部。基本上,对我来说,尝试解决它会导致尝试和错误。

在下文中,我给出了代码的精简示例,一次没有任何泛型(这样一个人就可以希望理解我想要实现的目标),而另一个则有一些更接近解决方案的补充。请更正我的第二个版本和/或指向特定的文档。(我有Java泛型的常规文档。但是我的代码似乎遇到了一些干扰性的挑战,因此很难找到正确的解决方案)

关于我的示例:有一个抽象的基本类型和几个实现的变体(仅给出一个)。方法combine()调用getOp1(),它决定(取决于<some condition>)是应该对自己的实例还是对新实例进行操作。计算后,它将返回目标实例。

abstract class Base {
    protected final Base getOp1() {
        if(Util.isConditionMet()) { return getNewInstance(); }
        else { return this; }
    }
    protected abstract Base getNewInstance(); // returns a new instance of an implementing class
    public abstract Base combine(Base other);
}

class Variant extends Base {
    public Variant getNewInstance() { return new Variant(); }   
    public combine(Variant op2) {
        Variant op1 = getOp1();
        op1.calculate(op2);
        return op1;
    }
    private void calculate(Variant other) { /* some code */ }
}

添加了一些泛型的版本。该版本有故障,无法编译。

abstract class Base<T extends Base<T>> {
    protected final T getOp1() {
         if(Util.isConditionMet()) { return getNewInstance(); }
         else { return this; }
    }
    protected abstract T getNewInstance(); // returns a new instance of an implementing class
    public abstract T combine(T other);
}

class Variant<T extends Variant<T>> extends Base<T> {
    protected T getNewInstance() { return new Variant(); }  
    public T combine(T op2) {
        T op1 = getOp1();
        op1.calculate(op2);
        return op1;
    }
    private void calculate(T other) { /* some code */ }
}

阅读 251

收藏
2020-11-30

共1个答案

小编典典

为了使此代码正常工作,您需要解决不兼容类型的问题:将T返回类型替换为Base<T>,并将结果强制转换Variant#getOp1()Variant<T>以允许对其进行调用calculate()(此处很安全,因为Variant#getOp1()始终返回Variant

abstract class Base<T extends Base<T>> {
    protected final Base<T> getOp1() {
         return condition() ? getNewInstance() : this;
    }
    protected abstract Base<T> getNewInstance(); 
    public abstract Base<T> combine(T other);
}



class Variant<T extends Variant<T>> extends Base<T> {
    protected Base<T> getNewInstance() { 
        return new Variant(); 
    }

    public Base<T> combine(T op2) {
        Variant<T> op1 = (Variant<T>) getOp1();   // <- explicit cast
        op1.calculate(op2);
        return op1;
    }

    private void calculate(Base<T> other) { 
        // ...
    }
}

顺便说一句,我仍然没有看到如此复杂的类型结构的原因。

2020-11-30