带有继承的Lombok @Builder
文章目录1。概述2。@ Builder*和继承2.1。定义问题2.2。解决问题2.3。使多个* @ Builder* s共存2.4. 支持更大的继承层次结构3。 @ SuperBuilder*和继承3.1. 应用注释3.2. 使用构建器4。结论原文:原文链接1。概述Lombok库提供了一种无需编写任何样板代码即可实现* Builder Pattern的好方法: [@Builder](https:/
文章目录
原文:原文链接
1。概述
Lombok库提供了一种无需编写任何样板代码即可实现* Builder Pattern的好方法: [@Builder](https:// projectlombok.org/features/Builder)*注释。
在这个简短的教程中,我们将专门学习涉及继承时如何处理@ Builder注释。我们将演示两种技术。一种依赖于标准的Lombok功能。另一个则利用了Lombok 1.18中引入的实验功能。
有关Builder注释的更广泛概述,请参考使用Lombok的@ Builder注释。
Project Lombok简介中也提供了有关Project Lombok库的详细信息。
2。@ Builder*和继承
2.1。定义问题
假设我们的Child类扩展了Parent类:
@Getter
@AllArgsConstructor
public class Parent {
private final String parentName;
private final int parentAge;
}
@Getter
@Builder
public class Child extends Parent {
private final String childName;
private final int childAge;
}
在扩展了此类的另一个类上使用@ Builder时,我们将在注释上收到以下编译错误:
隐式超级构造函数Parent()未定义。必须显式调用另一个构造函数
这是由于Lombok不考虑超类的字段,而仅考虑了当前类的字段。
2.2。解决问题
对我们来说幸运的是,有一个简单的解决方法。我们可以(使用我们的IDE甚至手动生成)基于字段的构造函数。这也包括超类的字段。我们用@ Builder而不是类来注释它:
@Getter
@AllArgsConstructor
public class Parent {
private final String parentName;
private final int parentAge;
}
@Getter
public class Child extends Parent {
private final String childName;
private final int childAge;
@Builder
public Child(String parentName, int parentAge, String childName, int childAge) {
super(parentName, parentAge);
this.childName = childName;
this.childAge = childAge;
}
}
这样,我们将能够从Child类访问便捷的构建器,这将使我们也可以指定Parent类的字段:
Child child = Child.builder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.build();
assertThat(child.getParentName()).isEqualTo("Andrea");
assertThat(child.getParentAge()).isEqualTo(38);
assertThat(child.getChildName()).isEqualTo("Emma");
assertThat(child.getChildAge()).isEqualTo(6);
2.3。使多个* @ Builder* s共存
如果超类本身使用@ Builder进行注释,则在注释Child类的构造函数时会出现以下错误:
返回类型与Parent.builder()不兼容
这是因为Child类正试图公开两个具有相同名称的Builders。
我们可以通过为至少一个构建器方法分配唯一的名称来解决此问题:
@Getter
public class Child extends Parent {
private final String childName;
private final int childAge;
@Builder(builderMethodName = "childBuilder")
public Child(String parentName, int parentAge, String childName, int childAge) {
super(parentName, parentAge);
this.childName = childName;
this.childAge = childAge;
}
}
然后,我们将能够通过Child.builder()获得 ParentBuilder,并通过Child.childBuilder()获得 ChildBuilder。
2.4. 支持更大的继承层次结构
在某些情况下,我们可能需要支持更深的继承层次结构。我们可以使用与以前相同的模式。让我们创建Child的子类。
@Getter
public class Student extends Child {
private final String schoolName;
@Builder(builderMethodName = "studentBuilder")
public Student(String parentName, int parentAge, String childName, int childAge, String schoolName) {
super(parentName, parentAge, childName, childAge);
this.schoolName = schoolName;
}
}
和以前一样,我们需要手动添加一个构造函数。这需要接受所有父类和子类的所有属性作为参数。然后,像以前一样添加@ Builder批注。通过在注释中提供另一个唯一的方法名称,我们可以获得Parent,Child或Student的构建器。
Student student = Student.studentBuilder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.schoolName("Baeldung High School")
.build();
assertThat(student.getChildName()).isEqualTo("Emma");
assertThat(student.getChildAge()).isEqualTo(6);
assertThat(student.getParentName()).isEqualTo("Andrea");
assertThat(student.getParentAge()).isEqualTo(38);
assertThat(student.getSchoolName()).isEqualTo("Baeldung High School");
然后,我们可以扩展此模式以处理任何继承深度。我们需要创建的构造函数可能会变得很大,但是您的IDE可以帮助您。
3。 @ SuperBuilder*和继承
如我们前面所述,Lombok的1.18版引入了* @ SuperBuilder*批注。我们可以使用它来以更简单的方式解决问题。
3.1. 应用注释
我们可以使建造者能够看到其祖先的属性。
为此,我们使用@ SuperBuilder批注对我们的类及其祖先进行批注。
让我们在这里演示我们的三层层次结构。请注意,简单父级和子级继承的原理是相同的:
@Getter
@SuperBuilder
public class Parent {
// same as before...
@Getter
@SuperBuilder
public class Child extends Parent {
// same as before...
@Getter
@SuperBuilder
public class Student extends Child {
// same as before...
当所有类都以这种方式注释后,我们将为子类获得一个构建器,该构建器也公开了父级的属性。
注意,我们必须注释所有类。 @ SuperBuilder不能在同一类层次结构中与@ Builder混合。这样做会导致编译错误。
3.2. 使用构建器
这一次,我们不需要定义任何特殊的构造函数。由@ SuperBuilder生成的生成器类的行为就像我们使用主Lombok @ Builder生成的生成器类一样:
Student student = Student.builder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.schoolName("Baeldung High School")
.build();
assertThat(student.getChildName()).isEqualTo("Emma");
assertThat(student.getChildAge()).isEqualTo(6);
assertThat(student.getParentName()).isEqualTo("Andrea");
assertThat(student.getParentAge()).isEqualTo(38);
assertThat(student.getSchoolName()).isEqualTo("Baeldung High School");
4。结论
我们已经看到了如何处理在利用继承的类中使用@ Builder注释的常见陷阱。
如果使用主要的Lombok @ Builder批注,我们还有一些额外的步骤可以使它起作用。但是,如果我们愿意使用实验性功能,那么@ SuperBuilder可以简化事情。
和往常一样,完整的源代码可在[GitHub上]获得(https://github.com/eugenp/tutorials/tree/master/lombok)。
更多推荐



所有评论(0)