Java generics involving inheritance and this

ε祈祈猫儿з 提交于 2020-01-22 03:14:10

问题


I have a (for me) complex Java generics problem. I read through some documentation and understand some but certainly not all of what I should. Basically, for me, trying to solve it would result in try and error.

In the following, I give a condensed example of my code, once without any generics (so one can hopefully understand what I want to achieve) and the other with some additions that come closer to the solution. Please correct my second version and/or point me to specific documentation. (I have general documentation of Java generics. But my code seems to have several interfering challenges and it is hard to a correct solution)

About my example: There is an abstract base type and several implementing variants (only one is given). Method combine() calls getOp1(), which decides (depending on <some condition>) if it should operate on its own instance or on a new one. After the calculation, it returns the target instance.

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 */ }
} 

The version with some generics added. This version is faulty and does not compile.

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 */ }
}

回答1:


To make this code working, you need to resolve incompatibility type issues: replace T returning types by Base<T> and cast result of Variant#getOp1() to Variant<T> to allow invoke calculate() on it (this is safe here because Variant#getOp1() always returns 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) { 
        // ...
    }
}

Btw, I still see no reason of such complicated type structure.




回答2:


I have seen a couple of such combinational, operational classes, though never too elaborate. Maybe inheritance is not the right tool.

Better to use a lookup mechanism for capabilities, features.

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);

This also allows dynamic changes, and combining things with respect to two aspects.



来源:https://stackoverflow.com/questions/33171797/java-generics-involving-inheritance-and-this

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!