我可以在java中使用方法链接而不执行不安全操作的抽象构建器类吗?

时间:2011-04-28 12:21:56

标签: java generics builder fluent-interface

我正在尝试为一些构建器类创建一个抽象基类,这样我就可以轻松地在Builder实现之间重用代码。我希望我的构建器支持方法链接,因此方法必须返回最具体类型的“this”实例。我想我可以用泛型来做这件事。不幸的是,如果不使用不安全的操作,我就无法做到这一点。有可能吗?

我正在尝试它(以及它如何工作)的示例代码如下。我想避免在“foo()”中输入T(导致未经检查的警告),可以这样做吗?

public class Builders
{
   public static void main( final String[] args )
   {
      new TheBuilder().foo().bar().build();
   }
}


abstract class AbstractBuilder<T extends AbstractBuilder<?>>
{
   public T foo()
   {
      // set some property
      return (T) this;
   }
}


class TheBuilder extends AbstractBuilder<TheBuilder>
{
   public TheBuilder bar()
   {
      // set some other property
      return this;
   }

   public Object build()
   {
      return new Object();
   }
}

3 个答案:

答案 0 :(得分:50)

您想在T中将extends AbstractBuilder<T>声明为AbstractBuilder

使用abstract protected方法获取this类型的T

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

    public T foo() {
        // set some property
        return getThis();
    }
}


class TheBuilder extends AbstractBuilder<TheBuilder> {
    @Override protected TheBuilder getThis() {
        return this;
    }
    ...
}

或者,删除泛型类型参数,依赖协变返回类型并使代码更清洁客户端(尽管通常它们将使用TheBuilder而不是基类的大部分实现细节),如果使用实施更详细。

答案 1 :(得分:8)

一种替代方法是不使用泛型,而是使用覆盖:

abstract class AbstractBuilder
{
   public AbstractBuilder foo()
   {
      // set some property
      return this;
   }
}

class TheBuilder extends AbstractBuilder
{
   @Override public TheBuilder foo()
   {
      super.foo(); return this;
   }
   public TheBuilder bar()
   {
      // set some other property
      return this;
   }

   public Object build()
   {
      return new Object();
   }
}

答案 2 :(得分:0)

这应该有所帮助:

abstract class AbstractBuilder<T extends AbstractBuilder<?>>
{
   public AbstractBuilder<T> foo()
   {
      // set some property
      return (AbstractBuilder<T>) this;
   }

   abstract AbstractBuilder<T> bar();
   abstract Object build();
}