我可以在Java中拥有一个带有方法链接的抽象构建器类而不执行不安全的操作吗?

2022-09-01 09:27:58

我正在尝试为某些生成器类创建一个抽象基类,以便我可以在生成器实现之间轻松重用代码。我希望我的构建器支持方法链接,因此方法必须返回最特定类型的“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();
   }
}

答案 1

您想要声明为 中的 .Textends AbstractBuilder<T>AbstractBuilder

使用方法获取类型 。abstract protectedthisT

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


答案 2

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

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

推荐