Reputation: 825
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{
....
List<? extends Bar> getFoo();
}
Right now a class that implements Bar returns objects of any class that implements Bar. I want to make it stricter so that the class that implements Bar returns a List of objects of only its type in getFoo().
Upvotes: 17
Views: 18797
Reputation: 60957
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() {
// ...
}
}
Upvotes: 25
Reputation: 10891
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.
Upvotes: 0
Reputation: 10891
I liked yshavit answer best but I could not understand the code. So I will try to write the code as I think it should be.
interface Bar
{
// stuff
// don't bother with the getFoo method
}
interface BarUtils
{
< T extends Bar > List < ? extends T > getFoo ( T bar ) ;
}
Upvotes: 0
Reputation: 43391
The 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. :)
Upvotes: 2
Reputation: 36601
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 itUpvotes: 2
Reputation: 1407
Maybe sth like this
public interface Bar {
....
List<? extends Bar> getFoo();
}
public class T implements Bar {
List<T> getFoo();
}
public class TestClass extends T {};
Upvotes: 0
Reputation: 12613
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.
Upvotes: 1