如何扩展在其方法中返回此类的类

时间:2015-04-07 14:46:58

标签: java inheritance libgdx

问题很简单,但我不确定是否可以这样做......

如果我们有像

这样的课程
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++;
    }
}

我们可以看到它只是一个带有私有成员和setter / getter的类。 有趣的是,为了允许方法链接,setter返回this

所以我们可以这样做:

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

这里的问题是当我尝试扩展该类时添加一些实现这样的接口的功能

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

    public void methodI() {
        // whatever
    }
}

似乎没问题,直到我开始像这样使用它

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

因为setFoo实际上正在返回A的实例,而不是B的实例,而且在methodI中不存在...

任何解决方法?感谢。

顺便说一下,我只是简单地编写了一个基本代码来理解,但是如果你想了解更多,我只是想扩展 libgdx 的一些基本类(比如Math.Vector2Math.Vector3)来实现 Poolable

5 个答案:

答案 0 :(得分:5)

B类可以覆盖方法setFoo并将返回类型更改为B,因为B是A的更具体的版本。重写的方法可以具有更具体的返回类型。 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;
    }
}

答案 1 :(得分:2)

你应该在这里使用泛型:

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
    }
}

现在您将能够使用此类链式呼叫:

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

答案 2 :(得分:1)

之前也遇到过这种情况。不要认为这是一个简单的解决方案。考虑覆盖所有setter方法:

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

答案 3 :(得分:0)

为了完整性(即我不认为这是更好的解决方案而不是上述方法,可能是合适的)并且肯定不是问题标题的答案,而是您问题的可能解决方案。

您可以考虑使用Java 8提供的default方法。它专门用于向现有类添加功能。

// 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);
    }

}

答案 4 :(得分:-2)

只需让setFoo()返回void,然后就可以了:

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