Java:在超类方法签名中返回子类

dow*_*ner 24 java interface subclass superclass

我正在研究一个问题,其中有几个实现Foo,伴随着几个FooBuilder.虽然它们Foo共享几个需要设置的常见变量,但它们也有不同的变量,需要各自FooBuilder实现某些特定功能.为了简洁起见,我想让安装FooBuilder人员使用方法链,比如:

public abstract class FooBuilder {
  ...

  public FooBuilder setA(int A) {
    this.A = A;
    return this;
  }

  ...
}
Run Code Online (Sandbox Code Playgroud)

public class FooImplBuilder extends FooBuilder{
  ...
  public FooImplBuilder setB(int B) {
    this.B = B;
    return this;
  }
  public FooImplBuilder setC(int C) {
    this.C = C;
    return this;
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

等等,有几种不同的FooBuilder实现方式.这在技术上完成了我想要的一切,但是,这种方法对执行方法链接时方法调用的顺序很敏感.以下是方法未定义的编译错误:

someFoo.setA(a).setB(b)...
Run Code Online (Sandbox Code Playgroud)

要求开发人员考虑链中方法调用的顺序.为了避免这种情况,我想让setter以FooBuilder某种方式返回实际的实现子类.但是,我不知道该怎么做.什么是最好的方法?

Don*_*oby 18

这是一个很好的问题,也是一个真正的问题.

在Jochen的回答中提到,在Java中处理它的最简单方法可能涉及使用泛型.

在这篇关于使用继承与流畅接口的博客文章中对这个问题和合理的解决方案进行了很好的讨论,该条目将泛型与getThis()构建器子类中的方法重写的定义相结合,以解决始终返回正确类的构建器的问题.


zer*_*dth 8

找到了这个很好的答案后,我现在正在分享它。

public class SuperClass<I extends SuperClass>
{
    @SuppressWarnings( "unchecked" ) // If you're annoyed by Lint.
    public I doStuff( Object withThings )
    {
        // Do stuff with things.
        return (I)this ; // Will always cast to the subclass. Causes the Lint warning.
    }
}

public class ImplementationOne
extends SuperClass<ImplementationOne>
{} // doStuff() will return an instance of ImplementationOne

public class ImplementationTwo
extends SuperClass<ImplementationTwo>
{} // doStuff() will return an instance of ImplementationTwo
Run Code Online (Sandbox Code Playgroud)


Joc*_*hen 5

泛型可能是这里的方法。

如果你声明 setA() 这样的东西(伪代码)

<T> T setA(int a)
Run Code Online (Sandbox Code Playgroud)

编译器应该能够找出真正的类型,如果不能,您可以在代码中给出提示,例如

obj.<RealFoo>setA(42)
Run Code Online (Sandbox Code Playgroud)

  • +1:http://egalluzzo.blogspot.com/2010/06/using-inheritance-with-fluent.html 对这种策略有很好的描述 (3认同)