我有一个(对我来说)复杂的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 */ }
}
答案 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
不过,我仍然没有看到这种复杂类型结构的原因。