【发布时间】:2013-12-13 04:39:48
【问题描述】:
我在设计并行类层次结构时遇到了一些编译器错误。这个问题似乎源于 Java 的限制,其中(与 C++ 不同)没有公共的“typedef”来允许从泛型类外部访问类型参数。我想下面的示例代码最能说明我的问题。
public interface Bean { }
public class GreenBean implements Bean { }
public class RedBean implements Bean { }
// All BreanCounter classes implement this interface and interact with their
// corresponding concrete bean classes.
public interface BeanCounter <B extends Bean> {
public void addBean(B bean);
public Collection<B> getBeans();
}
// DefaultBeanCounter implements logic shared by GreenBeanCounter and RedBeanCounter
public class DefaultBeanCounter <B extends Bean> implements BeanCounter<B> {
private List<B> beans = new ArrayList<B>();
@Override
public void addBean(B bean) { beans.add(bean); }
@Override
public Collection<B> getBeans() { return beans; }
}
public class GreenBeanCounter extends DefaultBeanCounter<GreenBean> { }
public class RedBeanCounter extends DefaultBeanCounter<RedBean> { }
通过上述设置,编译器抱怨以下代码:
public class BeanCounterMaster <C extends BeanCounter<? extends Bean>> {
public void mergeBeans(C des, C src) {
for (Bean bean : src.getBeans()) {
des.addBean(bean); //compiler error on this line
}
}
}
错误信息如下:
BeanCounter类型中的addBean(capture#2-of ? extends Bean)方法不适用于参数(Bean)
这可以理解但很尴尬,因为 src 和 des 显然属于同一类型。然而,我们不能移动它们的 bean,因为我们只能使用基本类型“Bean”。在 C++ 世界中,我们可以使用“C::BeanType”来指代具体的 bean 类型。为了解决这个问题,我决定将合并逻辑放入已知 bean 类型的 DefaultBeanCounter:
所以我添加了以下方法:
public interface BeanCounter <B extends Bean> {
public void mergeBeans(BeanCounter<B> anotherCounter);
}
public class DefaultBeanCounter <B extends Bean> implements BeanCounter<B> {
@Override
public void mergeBeans(BeanCounter<B> anotherCounter) {
for (B bean : anotherCounter.getBeans())
addBean(bean);
}
}
现在 BeanCounterMaster 看起来像:
public class BeanCounterMaster <C extends BeanCounter<? extends Bean>> {
public void mergeBeans(C des, C src) {
des.mergeBeans(src); // Still got compiler error
}
}
新的编译器错误显示:
BeanCounter类型中的mergeBeans(BeanCounter)方法不适用于参数(C)
我在这里错过了什么?
【问题讨论】: