0

I have a class A which contains a field of type A (similar to the way a Node in an implementation of a linked list has a Node nextNode) like so:

public class A {

    private A otherA;

    public A getOtherA() {
        return otherA;
    }
}

Then I have a class B with a bounded type parameter of <T extends A> which attempts to assign the return value from getOtherA() to a variable of type T:

public class B<T extends A> {

    public B(T t1) {
        T t2 = t1.getOtherA();
    }
}

The above code produces an error at the line

T t2 = t1.getOtherA();

and reads as

Incompatible types.  Required T, Found A.

My question is how (if possible) do I modify the code so that I can treat the return value of getOtherA() as type T. After all, t1 is of type T, T extends A and getOtherA() just returns an object of the same type as the object it belongs to. So why does T#getOtherA() not have a return type of T?

It seems to me that my compiler should be satisfied that t1.getOtherA() always returns an object of type T, but I suspect that I have a misunderstanding of generics, in which case I'll bite the bullet and just cast each one to my desired type.

Dziugas
  • 1,500
  • 1
  • 12
  • 28
  • 1
    Possibly because `getOtherA` returns and object of type `A` and not `T`? `T` can be `A` but there is no guarentee that and `A` is a `T`?.. // Maybe this answer ( https://stackoverflow.com/a/897973/2985796 ) can provide a clue? – KDecker Mar 09 '18 at 19:12

1 Answers1

2

The error is because getOtherA() returns an A, which is not necessarily a T.

You can get close to you requirements if you make A generic, with the type parameter intended to be the class A itself.

// Introduce type parameter T, upper bound itself.
class A<T extends A<T>> {
    protected T otherA;  // now of type T

    public T getOtherA() {  // now returns T
        return otherA;
    }
}

Any subclasses of A are expected to supply themselves as a type parameter:

class ASub extends A<ASub> {
    // Implementation
}

Or they can declare their own type parameter with a similar constraint:

class ASub<T extends ASub<T>> extends A<T> {
    // Implementation
}

This means that getOtherA can be typed to return an object of its own type.

Class B will supply its T to A.

class B<T extends A<T>> {
    public B(T t1) {
        T t2 = t1.getOtherA();
    }
}
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • I cannot use this solution because it would require me to edit the interface of A, but it fully answers my question so I'll accept. Thanks. – Dziugas Mar 09 '18 at 19:40
  • The bound on `T` in the declaration of `A` is unnecessary. `class A` is sufficient – newacct Apr 08 '18 at 02:39