Подтвердить что ты не робот

Как вызвать супер-конструктор в Ломбоке

У меня есть класс

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

У меня есть еще один класс B

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

lombok бросает ошибку, говоря, что он не может найти конструктор A(), явно называя это тем, что я хочу, чтобы ломбок выполнял это, чтобы дать аннотацию классу b, чтобы он генерировал следующий код:

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

Есть ли у нас аннотация для Ломбока?

4b9b3361

Ответ 1

Это невозможно в Ломбоке. Хотя это была бы очень хорошая функция, для этого требуется разрешение, чтобы найти конструкторы суперкласса. Суперкласс известен только по имени в момент вызова Lombok. Использование операторов import и classpath для поиска фактического класса не является тривиальным. И во время компиляции вы не можете просто использовать отражение, чтобы получить список конструкторов.

Это не совсем невозможно, но результаты с использованием разрешения в val и @ExtensionMethod показали нам, что это трудно и подвержено ошибкам.

Раскрытие информации: Я разработчик Lombok.

Ответ 2

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.

Ответ 3

Ломбок не поддерживает то, что указывается путем создания любого @Value аннотированного класса final (как вы знаете, используя @NonFinal).

Единственное обходное решение, которое я нашел, - объявить всех членов final самостоятельно и вместо этого использовать аннотацию @Data. Эти подклассы должны быть аннотированы @EqualsAndHashCode и нужны явные все конструкторы args, поскольку Lombok не знает, как создать один, используя все аргументы одного из суперкласса:

@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;
    }
}

В частности, конструкторы подклассов делают решение немного неопрятным для суперклассов со многими членами, извините.

Ответ 4

для суперклассов со многими членами я бы предложил вам использовать @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;
    }
}

Ответ 5

Если у дочернего класса больше членов, чем у родителя, это может быть сделано не очень чисто, но коротко:

@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;
   }
}