How to extend a class that returns this in its methods

The question is simple, but I'm not sure if this is possible ...

if we have a class like

class A { private int foo; public A(int bar) { this.foo = bar; } public A setFoo(int bar) { this.foo = bar; return this; } public int getFoo() { return this.foo; } public void doSomething() { this.foo++; } } 

we see that this is just a class with a private member and setter / getter. The interesting thing is that to enable the chain of methods, the setter returns this .

So, we can do such things:

 A a = new A(0); a.setFoo(1).doSomething(); 

The problem here is that when I try to extend this class, add some functions that implement an interface like this

 class B extends A implements I { public B(int bar) { this.super(bar); } public void methodI() { // whatever } } 

Everything seems to be fine until I start using it like that

 B b = new B(1); b.setFoo(2).methodI(); 

Since setFoo actually returns an instance of A , not an instance of B , but methodI not exist in methodI ...

Any workaround? Thanks.

By the way, I just wrote the basic code just to understand, but if you want to know more, I'm just trying to extend some of the main libgdx classes (for example, Math.Vector2 , Math.Vector3 ) to implement Poolable.

+5
source share
5 answers

Class B can override the setFoo method and change the return type to B because B is a more specific version of A. An overridden method can have a more specific return type. eg.

 class B extends A implements I { public B(int bar) { this.super(bar); } public void methodI() { // whatever } @Override public B setFoo(int bar) { this.foo = bar; return this; } } 
+5
source

Here you should use generics:

 public class A<T extends A<?>> { public T self() { return (T) this; } private int foo; public A(int bar) { this.foo = bar; } public T setFoo(int bar) { this.foo = bar; return self(); } public int getFoo() { return this.foo; } public void doSomething() { this.foo++; } } public class B<T extends B<?>> extends A<T> implements I { public B(int bar) { this.super(bar); } public void methodI() { // whatever } } 

Now you can use these chain calls:

 B b = new B(1); b.setFoo(2).methodI(); 
+2
source

They ran in earlier. Do not think that there is baked in a simple solution. Consider overriding all setter methods:

 class B extends A implements I { @Override public A setFoo(int bar) { super.setFoo(bar); return this; } } 
+1
source

For completeness (i.e., I do not consider this the best solution, besides the above, it just might be appropriate) and, of course, is not an answer to the name of your question, but may be a possible solution to your problem.

You can use the default methods offered by Java 8. This is specifically for adding functionality to existing classes.

 // From LibGDX Pool.Poolable interface Poolable { public void reset(); } // Class A untouched. class A { private int foo; public A(int bar) { this.foo = bar; } public A setFoo(int bar) { this.foo = bar; return this; } public int getFoo() { return this.foo; } public void doSomething() { this.foo++; } } // Extend Poolable to add the functionality. interface PoolableVector extends Poolable { default void reset() { // Not sure what you want to do here. } } // A Poolable A trivially made. class B extends A implements PoolableVector { public B(int b) { super(b); } } 
0
source

Just set setFoo () return void, and then you can do:

B b = new B(1); b.setFoo(2); b.methodI();

-2
source

All Articles