So I’m trying to create an interface with a generic function to be overrided by a subclass but I can’t find a way to do this.
I think a piece of code will be more explicit:
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);
}
error: The method run(A, World) in the type AgentStrategy is not applicable for the arguments (StrategistAgent, W)
but I cannot write :
StrategistAgent<A extends StrategistAgent<A>, W extends World>
EDIT: Ok I followed Mark Peters’ advice and removed the setStrategy method. Should be working now..
Right so the problem, as you’ve probably figured out by now, is that there is nothing saying that where your error occurs,
thisis an instance ofA. This is what I was getting at when I was saying that Generics really aren’t made for this sort of self-referential typing.You’ve got other problems in your design too, though. For starters the
Wthat you accept when you set the strategy might be a completely different class than theWthat you get whenperceptis called.So what is your way forward? Well, again I argue this depends on your glue code, the stuff that creates the agent and strategy and puts them together.
Since that glue code is in all likelihood going to know exactly what type of agent and strategy it’s dealing with, you probably don’t even benefit from making
setStrategyabstract. And once it’s not abstract, you can just deal with it in each subclass.Really all you need from your subclasses is a protected method
getStrategy. And if you’re forcing all your subclasses to provide that, you might as well force them to return theAas well:So this is one solution. I’ll have to think a bit more to think of a more elegant one though.