Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subclasses that inherit generic interfaces

Tags:

java

generics

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?

like image 446
phil Avatar asked Aug 23 '13 12:08

phil


2 Answers

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.

like image 138
Arash Saidi Avatar answered Nov 15 '22 05:11

Arash Saidi


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;
    }
}
like image 37
Peter Zeller Avatar answered Nov 15 '22 03:11

Peter Zeller