Как вызвать супер-конструктор в Ломбоке
У меня есть класс
@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;
}
}
Есть ли у нас аннотация для Ломбока?
Ответы
Ответ 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;
}
}