【问题标题】:How to build an object when we have inheritance relationship using lombok builder?当我们使用 lombok builder 有继承关系时如何构建对象?
【发布时间】:2016-01-04 12:39:34
【问题描述】:

在我的项目中,我使用 lombok 来避免为类编写 getter 和 setter。 另外,我使用 lombok.Builder 来构建对象,而不是编写 new Obeject() 然后设置所有值。

但是当我们有继承关系并且当我们想使用 lombok builder 构造子对象时,我没有得到父字段。

例如:

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Parent{
  private String nationality;
  .
  .
  // more columns
}

而 Child 类将是这样的:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Child extends Parent{
   private String firstName;
   private String lastName;
   .
   .
}

在我的测试类中,我需要构建子对象

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


}

请告诉我,有没有办法在龙目岛处理这种情况。

【问题讨论】:

  • 不确定,为什么被否决如果有什么可以改进的地方请告诉我

标签: java inheritance lombok


【解决方案1】:

上述解决方案有效,但是需要太多解决方法。此外,子类和父类的任何更改都需要在各处更改构造函数参数。

Lombok 引入了 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;
}

现在,可以使用下面的 Builder 类(@Builder 注释是不可能的)

ChildClass.builder().a("testA").b("testB").c("testC").build();

【讨论】:

    【解决方案2】:

    @Builder 无法确定您希望公开Parent 的哪些字段。

    @Builder 放在一个类上时,只有在该类上显式声明的字段才会添加到*Builder

    @Builder 放置在静态方法或构造函数上时,生成的*Builder 将为每个参数提供一个方法。

    此外,如果您使用的是@Builder,那么可以安全地假设至少Child 是不可变的吗?

    我提供了两个示例,一个是 Parent 是可变的,Child 是不可变的,另一个是 ParentChild 都是不可变的。

    不可变的父子关系

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-22
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      • 2019-01-12
      • 2019-09-17
      • 1970-01-01
      相关资源
      最近更新 更多