Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend a class that is returning this in their methods

The question is easy but I'm not sure it's possible to do it...

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 can see that it's just simply a class with a private member and a setter/getter. The interesting thing is, to allow method chaining, the setter is returning this.

So we can do things like this:

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

The problem here is when I try to extend that class add some functionality implementing an interface like this

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

    public void methodI() {
        // whatever
    }
}

It seems ok, until I start using it like this

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

Because setFoo is actually returning an instance of A, not an instance of B, and in A methodI doesn't exist...

Any workaround? Thanks.

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

like image 644
danikaze Avatar asked Apr 07 '15 14:04

danikaze


People also ask

Can a method extend a class?

You can extend the class and override just the single method you want to "extend".

How do you extend a method in Java?

Extends: In Java, the extends keyword is used to indicate that the class which is being defined is derived from the base class using inheritance. So basically, extends keyword is used to extend the functionality of the parent class to the subclass.

Which class has to extend for making a class?

A subclass is a class that “extends” an existing class; that is, it has the attributes and methods of the existing class, plus more. The first line uses the keyword extends to indicate that Deck extends the class CardCollection . That means a Deck object has the same instance variables and methods as a CardCollection .

Can a subclass be extended?

A subclass can be further subclassed. Normally, subclassing specializes or refines a class by adding variables and methods (you cannot remove or hide variables or methods by subclassing).


2 Answers

Class B can override the method setFoo 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. e.g.

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;
    }
}
like image 92
bhspencer Avatar answered Sep 20 '22 05:09

bhspencer


You should use generics here:

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 will be able to use such chained calls:

B b = new B(1);
b.setFoo(2).methodI();
like image 35
bedrin Avatar answered Sep 19 '22 05:09

bedrin