I am running into a problem with javas generics and overriding methods. Imagine I have a deep tree-like class hierarchy. The top-level class defines a method foo which takes 1 argument of type Strategy. Strategy has a generic type parameter.
Each class in my class hierarchy needs to override foo to limit the kind of Strategy it can be passed so that the generic type parameter of the strategy matches the declaring class. Below is an example:
abstract static class TopLevelClass {
static final Strategy<TopLevelClass> s1 = tlc -> System.out.println(tlc.getTopLevelAtt());
String getTopLevelAtt() {
return "TopLevelAtt";
}
void foo(Strategy<TopLevelClass> s) {s.bar(this);}
}
static class MidLevelClass extends TopLevelClass {
static final Strategy<MidLevelClass> s2 = mlc -> System.out.println(mlc.getMidLevelAtt());
String getMidLevelAtt() {
return "MidLevelAtt";
}
void foo(Strategy<MidLevelClass> s) {s.bar(this);}
}
static class LowLevelClass extends MidLevelClass {
static final Strategy<LowLevelClass> s3 = llc -> System.out.println(llc.getTopLevelAtt());
String getLowLevelAtt() {
return "LowLevelAtt";
}
void foo(Strategy<LowLevelClass> s) {s.bar(this);}
}
static interface Strategy<X> {
void bar(X x);
}
In this example I want to be able to call foo on instances of class LowLevelClass with any of the static references s1, s2 and s3 defined in TopLevelClass, MidLevelClass and LowLevelClass respectively. Ideally I would not have to call different methods foo1, foo2 or foo3 depending on the argument.
The code above does NOT compile in java. The compile-time-error is:
Name clash: The method foo(Strategy) of type MidLevelClass has the same erasure as foo(Strategy) of type TopLevelClass but does not override it
I doubt this can easily be resolved. I could just use raw-types and rely on run-time typechecks but I would rather keep type safety. What can I do to achieve this without sacrificing the type hierarchy or type safety? Please note that passing the Strategy in the constructor IS NOT an option for me! It must be possible to call foo multiple times over the life time of the object.
Edit:
I realize, that this problem is perhaps difficult to follow without knowing the circumstances surrounding it. I have opened a more detailed question explaining the background of my problem here: How to make this Strategy-Object pattern type safe