How do I enforce that the method getFoo() in the implementing class, returns a list of the type of same implementing class.
public interface Bar{
....
How about this:
interface Bar
{
// everything but getFoo ( ) ;
}
interface FooGetter < T >
{
List < ? extends T > getFoo ( ) ;
}
interface BarRef < T extends Bar & FooGetter < T > >
{
T get ( ) ;
}
anything that implements BarRef must implement T and anything that implements T must have the appropriately enforced getFoo method.
Unfortunately this cannot be enforced by Java's type system.
You can get pretty close, though, by using:
public interface Bar<T extends Bar<T>> {
List<T> getFoo();
}
And then your implementing classes can implement it like so:
public class SomeSpecificBar implements Bar<SomeSpecificBar> {
// Compiler will enforce the type here
@Override
public List<SomeSpecificBar> getFoo() {
// ...
}
}
But nothing stops another class from doing this:
public class EvilBar implements Bar<SomeSpecificBar> {
// The compiler's perfectly OK with this
@Override
public List<SomeSpecificBar> getFoo() {
// ...
}
}
You should infer the generic on Bar
:
public interface Bar<T extends Foo> {
...
List<T> getFoo();
}
You can just parameterize the method, but that will not ensure that the return type matches that of the class.
This is not possible in Java, but you might wonder what the use-case is to force this in the interface.
List<itself>
. And since you program against that specific class, the compiler has access to that specific return type and knows about itThe interface Bar<T extends Bar<T>>
answers already here are right, but I just wanted to add that if this is really something you want to enforce, you may want to look at composing your objects rather than using inheritance. Without knowing too much about your classes, it might look something like this:
public interface FooGetter<T> {
List<? extends T> getFoo();
}
public class FooComposer<T extends Bar> {
...
final T bar;
final FooGetter<T> barGetter;
}
Or it could look very different... but the main point is that if you want the two Ts to match, composition may be the answer.
Of course, even that can be circumvented using raw types... but then again, if someone does that, they're just using a raw List
, and when they get ClassCastExceptions you can safely hit them. :)
Maybe sth like this
public interface Bar {
....
List<? extends Bar> getFoo();
}
public class T implements Bar {
List<T> getFoo();
}
public class TestClass extends T {};