Есть ли способ обеспечить во время компиляции, что определенные поля в неизменяемом объекте установлены, сохраняя при этом роль аргументов ясной? - PullRequest
0 голосов
/ 05 апреля 2011

Я экспериментирую со способами создания неизменных объектов. Следующие объекты-застройщики весьма привлекательны, потому что они сохраняют роль аргументов в чистоте. Однако я хотел бы использовать компилятор для проверки того, что определенные поля установлены, как при вызове конструктора Immutable(). StrictImmutableBuilder обеспечивает эти проверки, но довольно шумно. Есть ли способ получить те же чеки, но в виде LaxImmutableBuilder? Возможно, используя аннотации?

public class Immutable {

    public static void main(String[] args) {

        new Immutable("13272873C", 23, false);
        // nice but what where those arguments?

        new LaxImmutableBuilder() {{
            refCode("13272873C");
            age(23);
            subscribed(false);
        }}.build();
        // now I know what each value represents
        // but what if I forgot to set one?

        new StrictImmutableBuilder() {
            public String refCode() { return "13272873C"; }

            public int age() { return 23; }

            public boolean subscribed() { return false; }
        }.build();
        // now I'm forced to set each field, but now 
        // we have the extra noise of "return"
        // and also "public" if we want to use
        // this outside the current package

        // is there another way? maybe using annotations?
    }

    private final String refCode;
    private final int age;
    private final boolean subscribed;

    public String getRefCode() {
        return refCode;
    }

    public int getAge() {
        return age;
    }

    public boolean isSubscribed() {
        return subscribed;
    }

    public Immutable(String a, int b, boolean c) {
        this.refCode = a;
        this.age = b;
        this.subscribed = c;
    }

}

abstract class StrictImmutableBuilder {
    public abstract String refCode();

    public abstract int age();

    public abstract boolean subscribed();

    public Immutable build() {
        return new Immutable(refCode(), age(), subscribed());
    }
}

abstract class LaxImmutableBuilder {

    private String refCode;
    private int age;
    private boolean subscribed;

    protected void refCode(String refCode) {
        this.refCode = refCode;
    }

    protected void age(int age) {
        this.age = age;
    }

    protected void subscribed(boolean subscribed) {
        this.subscribed = subscribed;
    }

    public Immutable build() {
        return new Immutable(refCode, age, subscribed);
    }

}

Ответы [ 2 ]

2 голосов
/ 05 апреля 2011

Вот шаблон, который я использую:

class YourClass {
  // these are final
  private final int x;
  private final int y;

  private int a;
  private int b;

  // finals are passed into the constructor
  private YourClass(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public static class Builder {
    // int x, int y, int a, int b
    // whatever's final is passed into constructor
    public Builder(int x, int y) {
      this.x = x;
      this.y = y;
    }
    // a and b are optional, so have with() methods for these
    public Builder withA(int a) {
      this.a = a;
      return this;
    }
    public Builder withB(int b) {
      this.b = b;
      return this;
    }
    public YourClass build() {
      YourClass c = new YourClass (x, y);
      c.a = a;
      c.b = b;
      return c;
    }
  }
}
0 голосов
/ 05 апреля 2011

есть такой трюк: Тип-безопасный шаблон Builder

http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/

но это просто безумие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...