所以我正在尝试创建一个带有泛型函数的接口,以便被子类覆盖,但我找不到这样做的方法。
我认为一段代码会更明确:
interface Agent<A extends Agent<A>> {
<W extends World> Iterable<Action<A,W>> percepts(W world);
<W extends World> void takeAction(Action<A,W> action, W world);
}
abstract class StrategistAgent<A extends StrategistAgent<A>> implements Agent<A> {
abstract public <W extends World> AgentStrategy<A,W> getStrategy();
abstract public <W extends World> void setStrategy(AgentStrategy<A,W> strategy);
@Override
<W extends World> Iterable<Action<A,W>> percepts(W world) {
return getStrategy().run(this, world);
}
}
interface AgentStrategy<A extends StrategistAgent<A>, W extends World> {
Iterable<Action<A,W>> run(A agent, W world);
void init(A agent, W world);
}
错误:AgentStrategy类型中的方法run(A,World)不适用于参数(StrategistAgent,W)
但我不能写:
StrategistAgent<A extends StrategistAgent<A>, W extends World>
编辑:好的,我按照Mark Peters的建议删除了setStrategy方法。应该现在正在工作..
答案 0 :(得分:2)
正确的问题,正如您现在可能已经想到的那样,没有任何迹象表明您的错误发生在哪里,this
是A
的一个实例。当我说Generics真的不是为了这种自我引用的打字时,我就是这样做的。
但是你的设计中也存在其他问题。对于初学者,您在设置策略时接受的W
可能与调用W
时获得的percept
完全不同。
那你前进的方向是什么?好吧,我再次认为这取决于您的胶水代码,创建代理和策略并将它们组合在一起的东西。
由于该胶水代码很可能确切地知道它正在处理的代理和策略的类型,因此您可能甚至不会使setStrategy
抽象受益。一旦它不是抽象的,你就可以在每个子类中处理它。
您的子类实际上只需要一个受保护的方法getStrategy
。如果你强迫所有子类提供它,你也可以强迫他们返回A
:
abstract class StrategistAgent<A extends StrategistAgent<A>> implements Agent<A> {
protected abstract <W extends World> AgentStrategy<A,W> getStrategy();
protected abstract A getSelf();
@Override
public <W extends World> Iterable<Action<A,W>> percepts(W world) {
return this.<W>getStrategy().run(getSelf(), world);
}
}
所以这是一个解决方案。我不得不考虑更多优雅的想法。