Suppose we have three classes - AbstractMessage, AbstractEngine, and AbstractAction. These three classes all reference each other in a generic fashion so each Engine has a corresponding message and action and you can refer to them directly in the code.
public class MyMessage<M extends AbstractMessage<M,E,A>, E extends AbstractEngine<M,E,A>, A extends AbstractAction<M,E,A>> {
This is working fine, but when I attempt to enforce behavior at the highest level I run into some problems. My AbstractAction class has an applyTo method defined thusly:
protected abstract M applyTo(E engine, Object guarantee);
and my AbstractEngine class has this
private final M apply(A action) {
return action.apply(this, this.guarantee);
}
And it is on this line that it balks - complaining that:
The method applyTo(E, Object) in the type AbstractAction<M,E,A> is not
applicable for the arguments (AbstractEngine<M,E,A>, Object)
Now the reason for this is clear - the E in question might be some OTHER AbstractEngine and there's no way to know if the subclass we're calling this from is actually an E.
My question is, how can I say for certainty that if you're going to class MyEngine extends AbstractEngine<M...,E...,A...> that MyEngine is MUST be an E? And to have this certainty baked into AbstractEngine?
Here is a small example that illustrates the problem.
class EngineExample {
static abstract class AbEng<A extends AbAct<A,M,E>, M extends AbMes<A,M,E>, E extends AbEng<A,M,E>> {
final M func(A act) {
return act.apply(this); // compile error here
}
}
static abstract class AbMes<A extends AbAct<A,M,E>, M extends AbMes<A,M,E>, E extends AbEng<A,M,E>> {
}
static abstract class AbAct<A extends AbAct<A,M,E>, M extends AbMes<A,M,E>, E extends AbEng<A,M,E>> {
abstract void apply(E e);
}
static class RealEng extends AbEng<RealAct, RealMes, RealEng> {
}
static class RealMes extends AbMes<RealAct, RealMes, RealEng> {
}
static class RealAct extends AbAct<RealAct, RealMes, RealEng> {
void apply(RealEng eng) {
System.out.println("applied!");
}
}
}