【问题标题】:Does lombok @Builder allow extendslombok @Builder 是否允许扩展
【发布时间】:2018-08-24 09:28:45
【问题描述】:

我有 2 节课:

import lombok.Builder;
@Builder
public class B extends A {
}

import lombok.Builder;
@Builder
public class A {
}

@BuilderB 我收到消息:

返回类型与 A.builder() 不兼容。

这是龙目岛的限制吗?还是我做错了什么?

如果我将@Builder 关闭A,那么B 上的构建器似乎不会在B 的构造函数中考虑A 中的字段。

【问题讨论】:

    标签: java eclipse lombok


    【解决方案1】:

    在使用带有 java 继承的 lombok 时遇到问题,在父类和子类上使用以下注释后解决:

    @EqualsAndHashCode(callSuper = true)

    @SuperBuilder

    @数据

    @AllArgsConstructor

    @NoArgsConstructor

    【讨论】:

      【解决方案2】:

      最新的 lombok 版本 1.18.2 包括 the new experimental @SuperBuilder。它支持来自超类(也包括抽象类)的继承和字段。唯一的要求是所有超类都必须有@SuperBuilder 注释。有了它,解决方法就这么简单:

      @SuperBuilder
      public class B extends A {
         private String b;
      }
      
      @SuperBuilder
      public class A {
          private String a;
      }
      
      B instance = B.builder().b("b").a("a").build();
      

      【讨论】:

      • 超类的构建器呢?我也可以使用A.builder()吗?
      • 当然,只要超类不是抽象的。
      【解决方案3】:

      我无法再重现您的确切问题,但这可能是因为龙目岛已经进化了。

      但是,您的部分问题是 be 的构建器不包含 a 的字段。这仍然是正确的,@AllArgsConstructor 也是如此。继承不是龙目岛的强项。

      Thad 说,既然你可以自己编写构造函数,并且可以将@Builder 放在构造函数上,那么下面的代码就会如你所愿地为 B 生成一个生成器:

      @Builder
      public class A {
          String a;
      }
      

      public class B extends A {
      
          @Builder
          B(String a, String b) {
              super(a);
              this.b = b;
          }
      
          String b;
      }
      

      【讨论】:

      • 所以没有 A 的构建器?
      【解决方案4】:

      只有通过解决方法 (See #78) 才能实现

      来自Reinhard.codes

      我们一直在类本身上使用@Builder,但您也可以将它放在类的构造函数或静态方法上。在这种情况下,Lombok 将为构造函数/方法的每个参数在构建器类上创建一个 setter 方法。这意味着您可以为该类的所有字段(包括其超类)创建一个带有参数的自定义构造函数。

      @AllArgsConstructor
      public class Parent {
        private String a;
      }
      
      public class Child extends Parent {
      
        private String b;
      
        @Builder
        private Child(String a, String b){
          super(a);
          this.b = b;
        }
      }
      

      【讨论】:

      • 虽然你有一个指向 lombok 存储库的链接,但已经提到了这个解决方法。
      【解决方案5】:

      在不知道 lombok 的实现细节或尝试它的情况下,我会说不,因为模式不允许。

      如果您实现构建器模式,您的所有方法(除了 build() )将始终具有构建器存在的类作为返回类型。

      这意味着 A 类的方法只会返回 A。B 也总是返回 B。 如果您现在让 B 从 A 扩展,它将不会覆盖 A 的方法,因为它的返回类型不匹配。反之亦然,它无法在 B 中实现构建器方法,因为这些方法已经存在于 A 中。它们不能通过 OOP 设计共存。

      您也许可以创建一个通用构建器,但这并不能解决问题。如果您真的需要从 A 扩展,您的问题可能来自构建器模式无法解决的另一个设计决策。

      我假设您不会扩展类,而是在您的构建器中拥有 lombok 应该支持的默认值。然后,这些默认值反映了默认情况下 A 类可能支持的内容。在您希望 B 做某事的用例中,您可以调用构建器方法并覆盖这些默认值。

      编辑:哦,也许have a look here

      【讨论】:

      • 这是对 Lombok 的推测(“不知道 Lombok 的实现细节”)。在 Lombok 之外,您可以编写具有继承层次结构的构建器,该继承层次结构与已构建类的继承层次结构一致。不过,它需要一些相当巴洛克式的泛型杂技。
      • 请阅读详细信息。我确实说过可以使用泛型来做到这一点。但是我知道 lombok 会进行一些自动生成,但在我看来,这与 OOP 相关的构建器模式有关。所以答案仍然有效。也许 lombok 可以做到这一点,但作者的语法是错误的,但我不知道这一点,因为我不详细了解 lombok。所以指出你,这是猜测。
      猜你喜欢
      • 2011-03-29
      • 1970-01-01
      • 2017-12-10
      • 2018-04-02
      • 2020-10-02
      • 2017-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多