Java generics parameters multiple levels


I'm trying to extend MutableLiveData in multiple classes, each one extends the previous, like (those following rows could be copy/pasted directly in java file to test/lint them):

class ALiveData<T> extends MutableLiveData<T> { } interface OneInterface { void methodOne(); } class BLiveData<K,T> extends ALiveData<OneInterface> { @Override public void observe(LifecycleOwner owner, Observer<? super OneInterface> observer) { // THIS IS OK } } interface TwoInterface<K,T> extends OneInterface { void mathodTwo(); } abstract class SomeClass<K,T> implements TwoInterface<K,T> { } class CLiveData<K,T> extends BLiveData<K,List<T>> { @Override public void observe(LifecycleOwner owner, Observer<? super TwoInterface<K,T>> observer) { // not valid in compilation } @Override public void observe(LifecycleOwner owner, Observer<SomeClass<K,T>> observer) { // not valid in compilation } @Override public void observe(LifecycleOwner owner, Observer<? super OneInterface> observer) { // this is the only accepted observer() but I don't want to // observe by its basic OneInterface because it doesn't have // all TwoInterface methods and I don't want the caller need // to cast it every time. } } //------- testing instantiations -------- { (new CLiveData<Byte,Integer>()).observe(null, new Observer<TwoInterface<Byte, Integer>>() { @Override public void onChanged(TwoInterface<Byte, Integer> byteIntegerTwoInterface) { } }); }

I would like to be able to CLiveData.observe() by passing a new Observer<TwoInterface<Byte,Integer>> and not the basic new Observer<? super OneInterface>, because who will observe CLiveData needs to use TwoInterface and not its basic OneInterface.

What am I missing?

0
Jul 1 at 5:41 AM
User Avataremandt
#java#android#generics#polymorphism

Accepted Answer

Observer<? super OneInterface> does not mean subclasses can replace it with anything they want. Subclasses must use Observer<? super OneInterface> as the argument type. Nothing else. That type means “the Observer type argument is a specific type which is not known at compile time, which might turn out to be OneInterface or might turn out to be a superclass of OneInterface.” It does not mean “subclasses can pick the type at compile time.”

If you want to vary the Observer argument, you need another generic type argument for it:

class BLiveData<K,T,D extends OneInterface> extends ALiveData<D> {
    @Override
    public void observe(LifecycleOwner owner, Observer<? super D> observer) {
        // ...
    }
}

class CLiveData<K,T> extends BLiveData<K,List<T>,TwoInterface<K,T>> {
    @Override
    public void observe(LifecycleOwner owner, Observer<? super TwoInterface<K,T>> observer) {
        // ...
    }
}
User AvatarVGR
Jul 1 at 9:01 PM
4