涉及继承和此的Java泛型

时间:2015-10-16 13:31:14

标签: java generics

我有一个(对我来说)复杂的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 */ }
}

2 个答案:

答案 0 :(得分:0)

我见过几个这样的组合操作课程,但从未过于复杂。也许继承不是正确的工具。

最好为功能和功能使用查找机制。

class Base {

    // Untyped
    private Map<Class<?>, Object> capabilities = new HashMap<>();

    protected <I> void register(Class<I> intf, I obj) {
        capabilities.put(intf, obj);
    }

    public <T> Optional<T> lookup(Class<T> intf) {
        Object obj = capabilities.get(intf);
        return obj == null ? Optional.emtpy() : Optional.of(intf.cast(obj));
    }
}

interface Flying {
    void fly(double altitude);
}

Base pelican = new Pelican();
Flying flying = pelical.lookup(Flying.class).orElse(null);
flying.fly(0.5);

这也允许动态变化,并结合两个方面的事情。

答案 1 :(得分:0)

要使此代码正常工作,您需要解决不兼容性类型问题:将T返回类型替换为Base<T>并将Variant#getOp1()的结果转换为Variant<T>以允许调用{ {1}}就可以了(这是安全的,因为calculate()始终返回Variant#getOp1()

Variant
不过,我仍然没有看到这种复杂类型结构的原因。