Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace a parameterized type with a more specific one

Consider the following setup:

We have an interface SuperType which is parameterized like this:

public interface SuperType<V> {
}

SuperType supports method chaining. Hence it defines another type parameter which captures the concrete implementing subtype returned by each method like this:

public interface SuperType<V, S extends SuperType<V, S>> {

    public S doSomething();
}

Let's consider an implementation of SuperType<V, S extends SuperType<V, S>>:

public class SubType<V> implements SuperType<V, SubType<V>> {

    private final V value;

    public SubType(V value) { this.value = value; }

    public SubType<V> doSomething() { return this; }
}

Someone instantiates SubType<V> using for example strings but provides Object for the type parameter V:

Object s = "Java Generics";
SubType<Object> x = new SubType<>(s);

Now we want to define another method for SuperType<V, S extends SuperType<V, S>> which takes a more specific type parameter of V and returns the same implementation type S but now parameterized with W extends V:

public interface SuperType<V, S extends SuperType<V, S>> {

    public S doSomething();

    public <W extends V, T extends SuperType<W, T>> T doMoreSpecific(Class<W> typeToken);
}

This new interface definition is intended to support:

Object s = "Java Generics";
SubType<Object> x = new SubType<>(s);
SubType<String> y = x.doMoreSpecific(String.class);

Here I struggle to implement SubType<V>. What I want to provide as an implementation is:

public class SubType<V> implements SuperType<V, SubType<V>> {

    private final V value;

    public SubType(V value) { this.value = value; }

    public SubType<V> doSomething() { return this; };

    public <W extends V> SubType<W> doMoreSpecific(Class<W> typeToken) {
        return new SubType<>((W) value);
    }
}

My Question is:

How should I define the signature for the method doMoreSpecific() in the type SuperType<V, S extends SuperType<V, S>> so that the implementation provided by SubType<V> implements SuperType<V, SubType<V>> is acceptable?

Or otherwise, which implementation and interface method definition would do the trick?

Or else, why can't we do this in Java?

like image 450
Harmlezz Avatar asked Jun 16 '15 07:06

Harmlezz


1 Answers

Using the following signature:

<W extends V> SuperType<W, ?> doMoreSpecific(Class<W> typeToken);

There might be some unsafe cases though that I have not been able to find yet, any criticism is welcome!

like image 118
sp00m Avatar answered Oct 07 '22 13:10

sp00m