我从以下代码段收到编译器错误。错误发生在指定的行:
static abstract class AbstractRoot<R extends Root<R>> implements Root<R> {
private final Map<Grouping, Phrase> m_ph;
AbstractSqlRoot() { this.m_ph = new HashMap<>(); }
@Override public PhraseBuilder<R> phrase() {
PhraseBuilder<R> fr = (PhraseBuilder<R>) m_ph.get(Grouping.PHRASE);
if (fr == null) {
--> fr = new PhraseBuilder<R>(this);
m_ph.put(Grouping.PHRASE, fr);
}
return fr;
}
哈希图 m_ph
是一种类型安全的异构容器。类型链接由Grouping
枚举类提供,因此代码中存在的转换是安全的。
以下是PhraseBuilder
(及其自己的AbstractPhraseBuilder
)的类定义:
public static abstract class AbstractPhrase<R extends Root<R>> implements Phrase {
private final List<Element> m_elem;
private final R m_root;
AbstractPhrase(R r)
{ m_elem = new ArrayList<>(); m_root = r; }
:
:
}
public static final class PhraseBuilder<R extends Root<R>> extends AbstractPhrase<R> {
public PhraseBuilder() { this(null); }
public PhraseBuilder(R r) { super(r); }
:
:
}
编译器报告:“不兼容的类型:
AbstractRoot<R>
无法转换为R,其中R是一个类型变量:R extends Root<R>
在类AbstractRoot
中声明。”我感到困惑。
AbstractRoot
被声明为实现Root<R>
,所以它应该与“扩展Root<R>
”定义的参数兼容。我没有看到指示的构造函数调用和类定义之间的冲突。有人能帮我解决这个困境吗?我卡住了。
更新:感谢下面给出的答案,我明白了我的错误所在。
SqlRoot<R>
接口的设计确实需要将R
发送到PhraseBuilder
类。代码已经修补如下以解决这个问题:static abstract class AbstractRoot<R extends Root<R>> implements Root<R> {
private final Map<Grouping, Phrase> m_ph;
AbstractSqlRoot() { this.m_ph = new HashMap<>(); }
@Override public PhraseBuilder<R> phrase() {
PhraseBuilder<R> fr = (PhraseBuilder<R>) m_ph.get(Grouping.PHRASE);
if (fr == null) {
--> fr = new PhraseBuilder<R>(typedThis());
m_ph.put(Grouping.PHRASE, fr);
}
return fr;
}
:
:
protected abstract R typedThis();
}
子类
ConcreteRoot
的类定义现在包括一个名为 typedThis()
的方法声明。虽然这并不是最理想的解决方案,因为该方法成为了类的导出API的一部分,但它解决了问题。static final class ConcreteRoot extends AbstractRoot<ConcreteRoot> {
ConcreteRoot() { super(); }
@Override protected ConcreteRoot typedThis() { return this; }
:
:
}
SqlRoot<R>
中的方法返回一个R。除非重构大量代码,否则没有其他办法。因此,new PhraseBuilder<Root<R>>(this)
对我没有帮助。我真的需要一个R
。 - scottb