1

I have an interface A and class B implementing A.

I have a method in A, called doX(Function<? super A, ? extends A> f). When I tried to implement it in B, by writing <T extends A> doX(Function<? super B, T> f), it doesn't compile. I tried a variant of other possible generics also doesn't work. Basically, my function wants to take in itself, and spits out some other item implementing A. By using PECS, it becomes <? super B>, however it is wrong. Now I am totally clueless about what I should write.

  • You can't change a function's type signature like that, unfortunately, but you should be able to write a private helper with the signature you describe here and then call it to implement the `doX` API from A. – Louis Wasserman Nov 06 '20 at 17:36
  • 2
    Since `? super B` *could* be a `B`, and since `B` is not compatible with `? super A`, it means that `? super B` is not *guaranteed* to be compatible with `? super A`, and hence the compiler rejects it. – Andreas Nov 06 '20 at 18:11

1 Answers1

1

...my function wants to take in itself, and spits out some other item implementing A

If this is your only requirement, we can do away with super clause.

  1. You said the function should take its current instance as input. We can acheive it by introducing a type parameter at interface A level.
  2. For returning another implementation of interface A, we can introduce a type parameter at the method level.

Below is the complete code

public class Subtyping {
    private interface A<T extends A<T>> {
        <S extends A<S>> S doX(Function<T, S> f);
    }
    private static class B implements A<B> {
        @Override
        public <S extends A<S>> S doX(Function<B, S> f) {
                return f.apply(this);
        }
    }
    private static class C implements A<C> {
        @Override
        public <S extends A<S>> S doX(Function<C, S> f) {
            return null;
        }
    }
    public static void main(String[] args) {
        B b = new B();
        C result = b.doX(v -> new C());
        System.out.println(result);
    }
}
Prasanna
  • 2,390
  • 10
  • 11