I have an interface that ensures objects can make copies of themselves:
public interface Duplicable<T extends Duplicable<T>> {
public T duplicate();
}
I now have
class X implements Duplicable<X>
but I also have a class Y that extends X.
This isn't a problem, until I need another generic class:
public class DoStuffWithDuplicable<T extends Duplicable<T>>
I can't use a generic version of DoStuffWithDuplicable using Y, since it does not implement Duplicable<Y>
but Duplicable<X>
since it inherits it from X.
So I tried
public class DoStuffWithDuplicable<T extends Duplicable<? super T>>
.. but this means later introducing an unsafe cast
(T) obj.duplicate()
in the code body. Also the class parameters are more convoluted and the usage of the class harder to understand. Any ideas how to get around this problem?
I may not have understood your question properly, but I'll give it a go.
First of all, why do you have an interface that extends itself like that?
What you can try is this:
public interface Duplicable<T> {
public T duplicate();
}
Then when you use another class where you want the generic parameter to be Duplicable, you do it like this:
public class X<T extends Duplicable<T>> {
code...
}
Now when you inherit from X, any generic component in the subclasses will have to be Duplicable.
It is not possible to do this in Java.
Assume you call obj.duplicate() on an object of type Y. Then the typesystem can only ensure that it will return an object of type X, since Y implements Duplicate<X>.
But you can just create a DoStuffWithDuplicable<X> and pass Y objects to it.
DoStuffWithDuplicable<X> blub = new DoStuffWithDuplicable<X>();
Y y = (Y) blub.doStuff(new Y());
For return values, the client of your library can just use safe casts, as he probably knows the concrete types.
An other option would be to use unsafe casts in the library and check the types manually:
class DoStuffWithDuplicable<T extends Duplicable<? super T>> {
T doStuff(T obj) {
@SuppressWarnings("unchecked")
T t = (T) obj.duplicate();
if (!t.getClass().equals(obj.getClass()))
throw new ClassCastException("...");
return t;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With