Есть ли хороший способ унаследовать класс Builder для добавления дополнительных параметров? - PullRequest
1 голос
/ 29 сентября 2019

Если я пытаюсь унаследовать конструктор для добавления дополнительных параметров, я получаю нежелательное требование, чтобы параметры устанавливались в определенном порядке.Например, позвольте мне построить два компоновщика для класса 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);
}

Если я вызываю withX () перед withY (),метод withY () не будет компилироваться, потому что метод withX () не возвращал класс PointBuilderWithY.Базовый класс PointBuilder не имеет метода withY ().

Я знаю, что могу добавить абстрактный метод withY () к базовому классу, но это побеждает точку.Я хочу ограничить использование метода withY () только теми объектами, которые в нем нуждаются.Другими словами, я хочу, чтобы компилятор ввел ограничение, которое withY () не может быть вызвано при использовании первого PointBuilder.В то же время я не хочу говорить своим пользователям, что параметры должны быть указаны в определенном порядке, потому что это может сбить с толку.Я предпочитаю писать надежные системы.Пользователи ожидают указывать опции в любом порядке, что облегчает использование класса.

Есть ли способ сделать это?

1 Ответ

0 голосов
/ 29 сентября 2019

В 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;
  }
}
...