1概要

Lombokライブラリは、定型コードを書かずに


https://en.wikipedia.org/wiki/Builder


pattern#Java

を実装するための優れた方法を提供します。 Builder]

アノテーション。

この短いチュートリアルでは、継承が関係している場合の

@ Builder

アノテーションの扱い方** を具体的に学習します。

アノテーションのより広範な概要については、https://www.baeldung.com/lombok-builder[Lombokの

@ Builder

アノテーションの使用]を参照することができます。

Project Lombokライブラリの詳細については、https://www.baeldung.com/intro-to-project-lombok[Project Lombokの紹介]を参照してください。


2ロンボク

@ビルダー

と継承


2.1. 問題を定義する


Child

クラスが

Parent

クラスを拡張するとしましょう。

@Getter
@AllArgsConstructor
public class Parent {
    private final String parentName;
    private final int parentAge;
}

@Getter
@Builder
public class Child extends Parent {
    private final String childName;
    private final int childAge;
}

そのような別のクラスを拡張するクラスで

@ Builder

を使用すると、注釈に対して次のようなコンパイルエラーが発生します。

暗黙のスーパーコンストラクタParent()は定義されていない。明示的に別のコンストラクタを起動しなければなりません。

これは、Lombokがスーパークラスのフィールドを考慮に入れず、現在のクラスのフィールドのみを考慮に入れていないという事実によるものです。


2.2. 問題を解決する

幸いなことに、単純な回避策があります。スーパークラスのフィールドも含むフィールドベースのコンストラクタを(私たちのIDEを使って、あるいは手動でも)生成し、クラスの代わりに

@ Builder

を使ってアノテーションを付けることができます。

@Getter
@AllArgsConstructor
public class Parent {
    private final String parentName;
    private final int parentAge;
}

@Getter
public class Child extends Parent {
    private final String childName;
    private final int childAge;

    @Builder
    public Child(String parentName, int parentAge, String childName, int childAge) {
        super(parentName, parentAge);
        this.childName = childName;
        this.childAge = childAge;
    }
}

これにより、

Child

クラスから便利なビルダーにアクセスできるようになります。これにより、

Parent

クラスのフィールドも指定できます。

Child child = Child.builder()
  .parentName("Andrea")
  .parentAge(38)
  .childName("Emma")
  .childAge(6)
  .build();

assertThat(child.getParentName()).isEqualTo("Andrea");
assertThat(child.getParentAge()).isEqualTo(38);
assertThat(child.getChildName()).isEqualTo("Emma");
assertThat(child.getChildAge()).isEqualTo(6);


2.3. 複数の

__ @ Builder

__を共存させる

スーパークラス自体に

@ Builder

という注釈が付けられている場合、

Child

クラスのコンストラクタに注釈を付けると、次のエラーが発生します。
































































_戻り型はParent.builder()と互換性がありません































































_

これは、

Child

クラスが両方の

Builders

を同じ名前で公開しようとしているためです。

この問題を解決するには、少なくとも1つのBuilderメソッドに固有の名前を割り当てます。

@Getter
@Builder
public class Parent {
    private final String parentName;
    private final int parentAge;
}

@Getter
public class Child extends Parent {
    private final String childName;
    private final int childAge;

    @Builder(builderMethodName = "childBuilder")
    public Child(String parentName, int parentAge, String childName, int childAge) {
        super(parentName, parentAge);
        this.childName = childName;
        this.childAge = childAge;
    }
}

これで、

Child.builder()

を介してParentBuilderを取得し、

Child.childBuilder()

を介して

ChildBuilder

を取得できるようになります。


3結論

継承を利用するクラスで

@ Builder

アノテーションを使用する際の一般的な落とし穴に対処する方法を見ました。

いつものように、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/lombok[over on Github]から入手できます。