J'ai un cours
@Value
@NonFinal
public class A {
int x;
int y;
}
J'ai une autre classe B
@Value
public class B extends A {
int z;
}
lombok génère une erreur en disant qu'il ne peut pas trouver le constructeur A(), appelez-le explicitement ce que je veux que lombok fasse est de donner une annotation à la classe b telle qu'elle génère le code suivant:
public class B extends A {
int z;
public B( int x, int y, int z) {
super( x , y );
this.z = z;
}
}
Avons-nous une annotation pour le faire à Lombok?
Ce n'est pas possible à Lombok. Bien que ce soit une fonctionnalité vraiment agréable, il faut résoudre le problème pour trouver les constructeurs de la classe supérieure. La super classe n'est nommée que lorsque Lombok est invoqué. L'utilisation des instructions d'importation et du chemin d'accès aux classes pour trouver la classe réelle n'est pas triviale. Et lors de la compilation, vous ne pouvez pas simplement utiliser la réflexion pour obtenir une liste de constructeurs.
Ce n’est pas tout à fait impossible, mais les résultats obtenus avec la résolution dans val
et @ExtensionMethod
nous ont appris que c’est difficile et susceptible d’erreurs.
Divulgation: Je suis un développeur de Lombok.
Lombok Issue # 78 référence cette page https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/ avec cette belle explication:
@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; } }
En conséquence, vous pouvez ensuite utiliser le générateur généré comme ceci:
Child.builder().a("testA").b("testB").build();
La documentation officielle explique cela, mais elle ne précise pas que vous pouvez la faciliter de cette manière.
J'ai également constaté que cela fonctionne bien avec Spring Data JPA.
Lombok ne prend pas en charge ce qui est également indiqué en faisant toute classe @Value
annotée final
(comme vous le savez en utilisant @NonFinal
).
La seule solution que j'ai trouvée consiste à déclarer tous les membres finaux et à utiliser plutôt l'annotation @Data
. Ces sous-classes doivent être annotées par @EqualsAndHashCode
et requièrent un constructeur explicite de tous les arguments, car Lombok ne sait pas en créer un en utilisant l'un des arguments de la super classe:
@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;
}
}
En particulier, les constructeurs des sous-classes rendent la solution un peu désordonnée pour les super-classes avec de nombreux membres, désolé.
pour les super-classes avec de nombreux membres, je vous suggère d'utiliser @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;
}
}
Si la classe enfant a plus de membres que de parents, cela pourrait être fait de manière pas très propre, mais de manière courte:
@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;
}
}