Dans mon projet, j'utilise lombok pour éviter d'écrire des getters et setters pour une classe. En outre, j'utilise lombok.Builder pour construire un objet au lieu d'écrire un nouveau Obeject () puis de définir toutes les valeurs.
Mais lorsque nous avons une relation d'héritage et que nous voulons construire un objet enfant à l'aide du générateur lombok, je n'obtiens pas le champ parent.
Par exemple:
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Parent{
private String nationality;
.
.
// more columns
}
Et la classe enfant serait quelque chose comme ceci:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Child extends Parent{
private String firstName;
private String lastName;
.
.
}
Dans ma classe de test, où j'ai besoin de construire un objet enfant
public class Test{
public void testMethod(){
Child child = Child.builder()
.firstName("Rakesh")
.lastName("SS")
.nationality("some text")// I am not able to set nationality
.build();
}
}
Veuillez me le faire savoir, existe-t-il un moyen de gérer ce scénario à lombok.
@Builder
n'a aucun moyen de déterminer quels champs de Parent
vous souhaitez exposer.
Quand @Builder
est placé sur une classe, seuls les champs explicitement déclarés sur cette classe sont ajoutés au *Builder
.
Quand @Builder
est placé sur une méthode statique ou un constructeur le *Builder
aura une méthode pour chaque argument.
De plus, si vous utilisez @Builder
alors est-il sûr de supposer qu'au moins Child
est censé être immuable?
Je fournis deux exemples, un où Parent
est modifiable et Child
est immuable et un où Parent
et Child
sont immuables.
import static org.junit.Assert.*;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.Value;
import lombok.experimental.NonFinal;
import org.junit.Test;
public class So32989562ValueTest {
@Value
@NonFinal
public static class Parent {
protected final String nationality;
}
@Value
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public static class Child extends Parent {
private final String firstName;
private final String lastName;
@Builder(toBuilder = true)
private Child(String nationality, String firstName, String lastName) {
super(nationality);
this.firstName = firstName;
this.lastName = lastName;
}
}
@Test
public void testChildBuilder() {
String expectedFirstName = "Jeff";
String expectedLastName = "Maxwell";
String expectedNationality = "USA";
Child result = Child.builder()
.firstName(expectedFirstName)
.lastName(expectedLastName)
.nationality(expectedNationality)
.build();
assertEquals(result.toString(), expectedFirstName, result.getFirstName());
assertEquals(result.toString(), expectedLastName, result.getLastName());
assertEquals(result.toString(), expectedNationality, result.getNationality());
}
}
import static org.junit.Assert.*;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.Value;
import org.junit.Test;
public class So32989562DataTest {
@Data
public static class Parent {
protected String nationality;
}
@Value
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public static class Child extends Parent {
private final String firstName;
private final String lastName;
@Builder(toBuilder = true)
private Child(String nationality, String firstName, String lastName) {
this.setNationality(nationality);
this.firstName = firstName;
this.lastName = lastName;
}
}
@Test
public void testChildBuilder() {
String expectedFirstName = "Jeff";
String expectedLastName = "Maxwell";
String expectedNationality = "USA";
Child result = Child.builder()
.firstName(expectedFirstName)
.lastName(expectedLastName)
.nationality(expectedNationality)
.build();
assertEquals(result.toString(), expectedFirstName, result.getFirstName());
assertEquals(result.toString(), expectedLastName, result.getLastName());
assertEquals(result.toString(), expectedNationality, result.getNationality());
}
}
La solution ci-dessus fonctionne, mais cela nécessite trop de solution. De plus, tout changement dans la classe enfant et parent nécessite de changer partout les arguments du constructeur.
Lombok a introduit des fonctionnalités expérimentales avec la version: 1.18.2 pour les problèmes d'héritage rencontrés avec l'annotation Builder, et peut être résolu avec l'annotation @SuperBuilder comme ci-dessous.
@SuperBuilder
public class ParentClass {
private final String a;
private final String b;
}
@SuperBuilder
public class ChildClass extends ParentClass{
private final String c;
}
Maintenant, on peut utiliser la classe Builder comme ci-dessous (ce n'était pas possible avec l'annotation @Builder)
ChildClass.builder().a("testA").b("testB").c("testC").build();