ぼけーっとLombok眺めてて。Valueって便利そうかもなぁって思った。
@Value
JuiceId
例えばジュースのIDのValueObjectを定義したいなーってときは
import lombok.Value; @Value public class JuiceId { int id; }
こう書いておけば、こんなクラスが生成される
import java.beans.ConstructorProperties; public final class JuiceId { private final int id; @ConstructorProperties({"id"}) public JuiceId(int id) { this.id = id; } public int getId() { return this.id; } public boolean equals(Object o) { if(o == this) { return true; } else if(!(o instanceof JuiceId)) { return false; } else { JuiceId other = (JuiceId)o; return this.getId() == other.getId(); } } public int hashCode() { boolean PRIME = true; byte result = 1; int result1 = result * 59 + this.getId(); return result1; } public String toString() { return "JuiceId(id=" + this.getId() + ")"; } }
動きはこんな感じか
import spock.lang.Specification import spock.lang.Unroll class JuiceIdSpec extends Specification { @Unroll def "new JuiceId(#a).equals(new JuiceId(#b)) == #c"() { expect: new JuiceId(a).equals(new JuiceId(b)) == c where: a | b || c 1 | 1 || true 1 | 2 || false } @Unroll def "new JuiceId(#a).getId() == #a"() { expect: new JuiceId(a).getId() == a where: _| a _| 1 _| 2 } }
fluent
個人的にfluentが好きなのでAccessorsアノテーション使って
import lombok.Value; import lombok.experimental.Accessors; @Accessors(fluent = true) @Value public class FluentJuiceId { int id; }
こうなるのが好き。Experimentalだけどね。
import java.beans.ConstructorProperties; public final class FluentJuiceId { private final int id; @ConstructorProperties({"id"}) public FluentJuiceId(int id) { this.id = id; } public int id() { return this.id; } public boolean equals(Object o) { if(o == this) { return true; } else if(!(o instanceof FluentJuiceId)) { return false; } else { FluentJuiceId other = (FluentJuiceId)o; return this.id() == other.id(); } } public int hashCode() { boolean PRIME = true; byte result = 1; int result1 = result * 59 + this.id(); return result1; } public String toString() { return "FluentJuiceId(id=" + this.id() + ")"; } }
import spock.lang.Specification import spock.lang.Unroll class FluentJuiceIdSpec extends Specification { @Unroll def "new FluentJuiceId(#a).id() == #a"() { expect: new FluentJuiceId(a).id() == a where: _| a _| 1 _| 2 } }
Accessors
fluentオプション(boolean)
trueの場合は pepper の getter は単に pepper() になって、setter は pepper(T newValue)になるよ。あと、chainオプションもtrueになるよ。
chainオプション
trueの場合は生成されたセッターはvoidじゃなくてreturn thisするよ。
なんだけど
@Value 使うかなぁ?どうかなぁ?って考えてみて、やっぱ使わなさそうって思った。
細かい初期化をしたいときが多いし、値オブジェクトを定義するときにフィールドをfinalにする必要もないかなって思うので、 @EqualsAndHashCode + @Getter + @ToString くらいにしそうだな。それと @Accessors(fluent=true)。
ま、でも面白かったや。さて、娘達とクッキーでも作ろっと。