web-dev-qa-db-ja.com

Lombokでスーパーコンストラクターを呼び出す方法

クラスがあります

@Value
@NonFinal
public class A {
    int x;
    int y;
}

別のクラスBがあります

@Value
public class B extends A {
    int z;
}

lombokはA()コンストラクターを見つけることができないというエラーをスローしています。明示的に呼び出すには、lombokに次のコードを生成するようにクラスbに注釈を付けます。

public class B extends A {
    int z;
    public B( int x, int y, int z) {
        super( x , y );
        this.z = z;
    }
}

Lombokでそれを行うための注釈はありますか?

79
user2067797

これはロンボク島では不可能です。これは本当に素晴らしい機能ですが、スーパークラスのコンストラクターを見つけるには解決が必要です。スーパークラスは、Lombokが呼び出された時点でのみ名前で認識されます。 importステートメントとクラスパスを使用して実際のクラスを見つけることは簡単ではありません。また、コンパイル中にリフレクションを使用してコンストラクターのリストを取得することはできません。

完全に不可能というわけではありませんが、valおよび@ExtensionMethodの解像度を使用した結果から、困難でエラーが発生しやすいことがわかりました。

開示:私はロンボク島の開発者です。

114
Roel Spilker

Lombok Issue#78 このページを参照 https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/ この素敵な説明:

@AllArgsConstructor 
public class Parent {   
     private String a; 
}

public class Child extends Parent {
  private String b;

  @Builder
  public Child(String a, String b){
    super(a);
    this.b = b;   
  } 
} 

その結果、生成されたビルダーを次のように使用できます。

Child.builder().a("testA").b("testB").build(); 

公式ドキュメント はこれを説明していますが、この方法でそれを促進できることを明示的に指摘していません。

また、Spring Data JPAでもうまく機能することがわかりました。

15
JJ Zabkar

Lombokは、@Value注釈付きクラスfinal@NonFinalを使用することでわかるように)を作成することで示されるものもサポートしません。

私が見つけた唯一の回避策は、すべてのメンバーを最終的に宣言し、代わりに@Data注釈を使用することです。これらのサブクラスには、@EqualsAndHashCodeアノテーションを付ける必要があり、Lombokはスーパークラスのall argsを使用して作成する方法を知らないため、明示的なall argsコンストラクターが必要です。

@Data
public class A {
    private final int x;
    private final int y;
}

@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
    private final int z;

    public B(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }
}

特に、サブクラスのコンストラクターは、多くのメンバーを持つスーパークラスの場合、ソリューションを少し乱雑にします。申し訳ありません。

6
Arne Burmeister

多くのメンバーを持つスーパークラスの場合、@ Delegateを使用することをお勧めします

@Data
public class A {
    @Delegate public class AInner{
        private final int x;
        private final int y;
    }
}

@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
    private final int z;

    public B(A.AInner a, int z) {
        super(a);
        this.z = z;
    }
}
4
Kris

子クラスが親よりも多くのメンバーを持っている場合、それはあまりきれいではなく、短い方法で行うことができます:

@Data
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class User extends BaseEntity {
    private @NonNull String fullName;
    private @NonNull String email;
    ... 

    public User(Integer id, String fullName, String email, ....) {
        this(fullName, email, ....);
        this.id = id;
    }
}

@Data
@AllArgsConstructor
abstract public class BaseEntity {
   protected Integer id;

   public boolean isNew() {
      return id == null;
   }
}
2
GKislin