java 当我们使用 lombok builder 有继承关系时如何构建对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32989562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to build an object when we have inheritance relationship using lombok builder?
提问by Rakesh
In my project, I am using lombok to avoid writing getters and setters for a class. Also, I am using lombok.Builder to build an object instead of writing new Obeject() and then setting all the values.
在我的项目中,我使用 lombok 来避免为类编写 getter 和 setter。此外,我正在使用 lombok.Builder 来构建一个对象,而不是编写 new Obeject() 然后设置所有值。
But when we have inheritance relationship and when we want to construct child object using lombok builder, I am not getting parent's field.
但是当我们有继承关系并且我们想使用 lombok builder 构造子对象时,我没有得到父级的字段。
For example:
例如:
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Parent{
private String nationality;
.
.
// more columns
}
And Child class would be something like this:
Child 类将是这样的:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Child extends Parent{
private String firstName;
private String lastName;
.
.
}
In my test class, where I need to build child object
在我的测试类中,我需要在其中构建子对象
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();
}
}
Please let me know, is there any way to handle this scenario in lombok.
请让我知道,有没有办法在 lombok 中处理这种情况。
回答by Jeff
@Builder
has no way to determine which fields of Parent
you wish to expose.
@Builder
无法确定Parent
您希望公开哪些字段。
When @Builder
is placed on a class, only fields explicitly declared on that class are added to the *Builder
.
当@Builder
放在一个类上时,只有在该类上显式声明的字段才会添加到*Builder
.
When @Builder
is placed on a static method or a constructor the resulting *Builder
will have a method for each argument.
当@Builder
放置在静态方法或构造函数上时,结果*Builder
将具有每个参数的方法。
Also if you are using @Builder
then is it safe to assume that at least Child
is meant to be immutable?
此外,如果您正在使用,@Builder
那么假设至少Child
是不可变的是否安全?
I supply two examples, one where Parent
is mutable and Child
is immutable and one where both Parent
and Child
are immutable.
我提供了两个例子,一个Parent
是可变和Child
不可变的,一个是Parent
和Child
都是不可变的。
Immutable Parent and Child
不可变的父子
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());
}
}
Mutable Parent, Immutable Child:
可变父级,不可变子级:
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());
}
}
回答by Amit Kaneria
Above solution works, however that requires too much workaround. And further any changes in child and parent class requires changing constructor arguments everywhere.
上述解决方案有效,但这需要太多的解决方法。此外,子类和父类的任何更改都需要在任何地方更改构造函数参数。
Lombok has introduced experimental features with version: 1.18.2 for inheritance issues faced with Builder annotation, and can be resolved with @SuperBuilder annotation as below.
Lombok 已经在 version: 1.18.2 中引入了实验性功能,用于解决 Builder 注解面临的继承问题,可以使用 @SuperBuilder 注解解决,如下所示。
@SuperBuilder
public class ParentClass {
private final String a;
private final String b;
}
@SuperBuilder
public class ChildClass extends ParentClass{
private final String c;
}
Now, one can use Builder class as below (that was not possible with @Builder annotation)
现在,可以使用如下的 Builder 类(@Builder 注释无法实现)
ChildClass.builder().a("testA").b("testB").c("testC").build();