返回具有泛型的对象子类

对于抽象类,我想定义一个为子类返回“this”的方法:

public abstract class Foo {
    ...
    public <T extends Foo> T eat(String eatCake) {
        ...
        return this;
    }
}  

public class CakeEater extends Foo {}

我希望能够做这样的事情:

CakeEater phil = new CakeEater();
phil.eat("wacky cake").eat("chocolate cake").eat("banana bread");

可以说,香蕉面包会抛出一个非法的论据,上面写着“不是蛋糕!


答案 1
public abstract class Foo<T extends Foo<T>>  // see ColinD's comment
{
    public T eat(String eatCake) 
    {
        return (T)this;
    }
}

public class CakeEater extends Foo<CakeEater> 
{
    public void f(){}
}

编辑

要求子类以某种方式行为是没有问题的,这种方式超出了静态类型可以检查的范围。我们一直在这样做 - 一页又一页的纯英语来指定你如何编写子类。

另一个建议的解决方案,具有协变返回类型,必须执行相同的操作 - 要求子类实现者用简单的英语返回的类型。该要求不能通过静态类型化来指定。this


答案 2

从客户端的角度来看,有品位的方法(通常是你想要采取的方法)是使用协变返回类型,这是为了支持泛型而添加的,正如Michael Barker所指出的那样。

稍微不那么有品位,但更有品位的是演员添加一个方法:getThis

public abstract class Foo<T extends Foo<T>> {
    protected abstract T getThis();

    public T eat(String eatCake) {
        ...
        return getThis();
    }
}

public class CakeEater extends Foo<CakeEater> {
    @Override protected CakeEater getThis() {
        return this;
    }
}

推荐