如何在带有最终字段的Abstract类上使用Lombok @SuperBuilder [英] How to use Lombok @SuperBuilder on Abstract classes with final fields
问题描述
使用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时初始化Child
和Parent
类上的所有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屋!