如果我尝试继承一个构建器以添加更多选项,那么我会不必要地要求以特定顺序设置选项。例如,让我为类java.awt.geom.Point2D构建两个构建器。在基本构建器中,我们只能设置X,但是在扩展基本构建器的第二个构建器中,我们还可以设置Y:

private static class PointBuilder{
  private double x = 0.0;
  protected double y = 0.0;

  PointBuilder withX(double x) {
    this.x = x;
    return this;
  }

  Point2D build() {
    return new Point2D.Double(x, y);
  }
}

private static class PointBuilderWithY extends PointBuilder {
  PointBuilder withY(double y) {
    this.y = y;
    return this;
  }
}

public static void main(String[] args) {

  Point2D pt1 = new PointBuilder()
      .withX(5.0)
//      .withY(3.0)  // withY() doesn't compile, which is the intended behavior
      .build();

  // I can use a PointBuilderWithY only if I set the Y option first.
  Point2D pt2 = new PointBuilderWithY()
      .withY(3.0)
      .withX(5.0)
      .build();

  // If I set the X option first, the Y option doesn't build!
  Point2D pt3 = new PointBuilderWithY()
      .withX(5.0)
      .withY(3.0) // Won't compile! withX() didn't return a PointBuilderWithY
      .build();

  System.out.println(pt1);
  System.out.println(pt2);
  System.out.println(pt3);
}


如果我在withY()之前调用withX(),则withY()方法将无法编译,因为withX()方法未返回PointBuilderWithY类。 PointBuilder基类没有withY()方法。

我知道我可以在基类中添加一个抽象的withY()方法,但是这很有意义。我想将withY()方法的使用限制为仅需要它们的那些对象。换句话说,我希望编译器强制执行使用第一个PointBuilder时不能调用withY()的限制。同时,我不想告诉用户必须按一定顺序指定选项,因为这会造成混淆。我更喜欢编写万无一失的系统。用户期望以任何顺序指定选项,这使类更易于使用。

有没有办法做到这一点?

最佳答案

PointBuilderWithY中,重写所有PointBuilder的方法以返回PointerBuilderWithY实例。

private static class PointBuilderWithY extends PointBuilder {
  @Override
  PointBuilderWithY withX(double x) {
    return (PointBuilderWithY) super.withX(x);
  }

  PointBuilderWithY withY(double y) {
    this.y = y;
    return this;
  }
}

10-04 11:57