0

I have a generic class A<T> and a subclass B extends A<String>. The class A have a method which returns this (so an A<T>). The problem is, if I call the method on a B object, it will return a A<String> and I have to cast to B, but B is the same as A<String>, isn't it ? So I shouldn't have to cast ...

dblouis
  • 568
  • 1
  • 5
  • 18
  • is a `porsche` the same as a every `car`? – SomeJavaGuy Aug 16 '16 at 10:57
  • 1
    Please show your code... it sounds like you can use a covariant return type. – Andy Turner Aug 16 '16 at 10:57
  • 1
    You need the [return SELF](https://stackoverflow.com/questions/7354740/is-there-a-way-to-refer-to-the-current-type-with-a-type-variable) pattern. It's a bit ugly, but works. This is an example of the [curiously recurring template pattern](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). – Boris the Spider Aug 16 '16 at 10:57

3 Answers3

1

If your method returns A<String> it can be an object of type B but it does not have to be!

If you have a superclass of type car and BMW extends car.

Consider a factory that creates a car. The method returns car - this can be a BMW but it does not have to be a BMW.

Stefan
  • 2,603
  • 2
  • 33
  • 62
  • 1
    Because I could create another class which also extends A, I have only one so I did not see that ... – dblouis Aug 16 '16 at 11:01
  • @L.DUPRÉBERTONI this isn't really an answer to the question, which has a good solution. If I know that I have a `B`, and a method in the superclass returns `this`, then I would expect it to return a `B`; but the method will actually return an `A`. The way around this is the curiously recurring template pattern. – Boris the Spider Aug 16 '16 at 11:14
  • 1
    @BoristheSpider the question was about the understanding why he has to cast - I think I clearly answered this question. If you find yourself having another question feel free to post it as an answer to his question – Stefan Aug 16 '16 at 11:15
  • The point is that "_[t]he class `A` have a method which returns `this`_". If have created a `new B()` then we know that `this` can never by _anything else_. This answer answers a different question, not the question asked. I believe that the OP doesn't really understand the problem, and has selected the wrong answer... – Boris the Spider Aug 16 '16 at 11:32
0

I overrided the method and cast the returned value so that I don't have to do it everywhere. Thanks @AndyTurner

dblouis
  • 568
  • 1
  • 5
  • 18
0

You don't even have to cast. You can override the method and change the return type to B, as it's still an A<String> which is an A<T>, so it's valid for B.

class A<T> {

    public A<T> return_this() {
        return this;
    }

}

class B extends A<String> {

    @Override
    public B return_this() {
        return this;
    }


}

So you can do this:

B b = new B();
A<String> a = b.return_this(); //Because B extends A<String>
B b = b.return_this();
germanfr
  • 547
  • 5
  • 19
  • This does work, but becomes quickly untenable if there are large number of methods. – Boris the Spider Aug 16 '16 at 11:35
  • You can do this, or you can cast each time you call a method. – germanfr Aug 16 '16 at 11:39
  • As I said it depends. This solution is simple and works when you have one or two methods and one or two classes in the hierarchy. It becomes unmaintainable if there are a large number of methods returning self types; such as in a fluent accessor or builder pattern. In that case the curiously recurring template pattern is required. Casting is never an option however. – Boris the Spider Aug 16 '16 at 11:43