如何在带有最终字段的Abstract类上使用Lombok @SuperBuilder [英] How to use Lombok @SuperBuilder on Abstract classes with final fields

查看:1209
本文介绍了如何在带有最终字段的Abstract类上使用Lombok @SuperBuilder的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Lombok注释@Data@SuperBuilder

给出以下类

@Data
@SuperBuilder
public abstract class Parent {

    protected final String userId;
    protected final Instant requestingTime;
}

@Data
@SuperBuilder
public class Child extends Parent {

    private final Instant beginningDate;
    private final Instant endingDate;
    private final Collection<String> fields;
}

我在Child类中的@Data批注上出现以下错误:

隐式超级构造函数Parent()未定义.必须显式调用另一个构造函数.

是否有一种方法可以在Child类的@Data注释上配置非默认构造函数,以便在调用Builder时初始化ChildParent类上的所有final字段?

我已经在子类和父类上尝试了@Data@Getter@Setter批注与@SuperBuilder批注的几种不同组合,但是还没有找到可行的解决方案.我正在使用Lombok 1.18.10.

作为参考,与该问题相关

EDIT

这实际上是Lombok应该在SuperBuilder.build()操作上构造和调用的构造函数.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

根据要求,这就是我希望在Child对象上调用生成器的方式.

final Child child = Child.Builder()
                         .userId(<value>)
                         .requestingTime(<value>)
                         .beginningDate(<value>)
                         .endingDate(<value>)
                         .fields(<value>)
                         .build();

解决方案

AFAIK,@Data生成@NoArgsConstructor,这是错误的.实际上,@Data本身是错误的,因为它是针对可变类的. @Value会更好,但也无法处理超级构造函数.

因此,删除@Data,添加@Getter@EqualsAndHashCode@ToString,以及您需要的任何内容.不要忘记在子类中添加callSuper=true.


这实际上是Lombok应该在SuperBuilder.build()操作上构造和调用的构造函数.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

不,这不是SuperBuilder的工作方式.实际上,这是龙目岛无法做到的,因为它看不到超级字段.相反,构建器使用的是类似

的东西

public Child(ChildBuilder b) {    
    super(b);
    this.beginningDate = b.beginningDate;
    this.endingDate = b.endingDate;
    this.fields= b.fields;
}

您可以相信扬·里克(Jan Rieke)所说的话.

Given the following classes with the Lombok annotations @Data and @SuperBuilder

@Data
@SuperBuilder
public abstract class Parent {

    protected final String userId;
    protected final Instant requestingTime;
}

@Data
@SuperBuilder
public class Child extends Parent {

    private final Instant beginningDate;
    private final Instant endingDate;
    private final Collection<String> fields;
}

I am getting the following error appearing over the @Data annotation in the Child class:

Implicit super constructor Parent() is undefined. Must explicitly invoke another constructor.

Is there a way to configure a non-default constructor on the Child class's @Data annotation in order to have all final fields on both the Child and Parent classes initialized when invoking the Builder?

I have tried a few different combinations of the @Data, @Getter, @Setter annotations with the @SuperBuilder annotation on both the child and parent classes, but haven't found a working solution yet. I am using Lombok 1.18.10.

For reference, this question is related

EDIT

This is effectively the constructor that Lombok should be constructing and invoking on the SuperBuilder.build() operation.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

As requested, this is how I would expect to invoke the builder on the Child object.

final Child child = Child.Builder()
                         .userId(<value>)
                         .requestingTime(<value>)
                         .beginningDate(<value>)
                         .endingDate(<value>)
                         .fields(<value>)
                         .build();

解决方案

AFAIK, @Data generates a @NoArgsConstructor, which is just wrong. Actually, @Data is wrong per se, as it's meant for mutable classes; @Value would be better, but it can't deal with the super constructor either.

So remove @Data, add @Getter, @EqualsAndHashCode, @ToString and whatever you need. Don't forget to add callSuper=true in the subclass.


This is effectively the constructor that Lombok should be constructing and invoking on the SuperBuilder.build() operation.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

No, that's not how SuperBuilder works. This is actually Lombok can't do as it can't see the super fields. Instead, the builder uses something like

public Child(ChildBuilder b) {    
    super(b);
    this.beginningDate = b.beginningDate;
    this.endingDate = b.endingDate;
    this.fields= b.fields;
}

You can believe what Jan Rieke says, he wrote it.

这篇关于如何在带有最终字段的Abstract类上使用Lombok @SuperBuilder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆