简体   繁体   English

当我们使用lombok builder有继承关系时如何构建对象?

[英]How to build an object when we have inheritance relationship using lombok builder?

In my project, I am using lombok to avoid writing getters and setters for a class. 在我的项目中,我使用lombok来避免为一个类编写getter和setter。 Also, I am using lombok.Builder to build an object instead of writing new Obeject() and then setting all the values. 此外,我使用lombok.Builder来构建一个对象,而不是编写新的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中处理这种情况。

@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是不可变的,另一个是ParentChild都是不可变的。

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());
    }
}

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针对Builder注释面临的继承问题引入了版本:1.18.2的实验性功能,可以使用@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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM