我从下面的代码段收到编译器错误。在所指示的线发生了错误:泛型类型错误:实例无法转换为其自己的类型?
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;
}
在HashMap中m_ph
是一种类型安全异质容器。类型链接由Grouping
enum类提供,因此代码中的转换是安全的。
类定义为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>
”定义的参数兼容。我没有看到指定的构造函数调用和类定义之间的冲突。
任何能帮助我解决这个难题的人?我卡住了。
UPDATE:由于下面给出的答案,我得到我哪里错了。 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; }
:
:
}
谢谢你。不幸的是,当我为这些东西设计API时,我确实需要在接口'SqlRoot'中返回一个'R'的方法。我看到我出错的地方。从子类获得'R'的解决方案在API上留下可见的瑕疵(这个类不是导出的API的一部分),但它允许我继续前进。谢谢。 –
scottb
2015-01-21 13:15:57