Reputation: 2452
I have a class
@Value
@NonFinal
public class A {
int x;
int y;
}
I have another class B
@Value
public class B extends A {
int z;
}
lombok is throwing an error saying it can't find A() constructor, explicitly call it what I want Lombok to do is to give annotation to class b such that it generates the following code:
public class B extends A {
int z;
public B( int x, int y, int z) {
super( x , y );
this.z = z;
}
}
Do we have an annotation to do that in Lombok?
Upvotes: 232
Views: 324432
Reputation: 825
Version 1.18 of Lombok introduced the @SuperBuilder annotation. We can use this to solve our problem in a simpler way.
You can refer to https://www.baeldung.com/lombok-builder-inheritance#lombok-builder-and-inheritance-3.
so in your child class, you will need these annotations:
@Data
@SuperBuilder
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
in your parent class:
@Data
@SuperBuilder
@NoArgsConstructor
Upvotes: 48
Reputation: 18000
If child class has more members, than parent, it could be done not very clean, but short way:
@Data
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class User extends BaseEntity {
private @NonNull String fullName;
private @NonNull String email;
...
public User(Integer id, String fullName, String email, ....) {
this(fullName, email, ....);
this.id = id;
}
}
@Data
@AllArgsConstructor
abstract public class BaseEntity {
protected Integer id;
public boolean isNew() {
return id == null;
}
}
Upvotes: 4
Reputation: 81
for superclasses with many members I would suggest you to use @Delegate
@Data
public class A {
@Delegate public class AInner{
private final int x;
private final int y;
}
}
@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
private final int z;
public B(A.AInner a, int z) {
super(a);
this.z = z;
}
}
Upvotes: 8
Reputation: 20594
Lombok does not support that also indicated by making any @Value
annotated class final
(as you know by using @NonFinal
).
The only workaround I found is to declare all members final yourself and use the @Data
annotation instead. Those subclasses need to be annotated by @EqualsAndHashCode
and need an explicit all args constructor as Lombok doesn't know how to create one using the all args one of the super class:
@Data
public class A {
private final int x;
private final int y;
}
@Data
@EqualsAndHashCode(callSuper = true)
public class B extends A {
private final int z;
public B(int x, int y, int z) {
super(x, y);
this.z = z;
}
}
Especially the constructors of the subclasses make the solution a little untidy for superclasses with many members, sorry.
Upvotes: 12
Reputation: 3689
Lombok Issue #78 references this page https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/ with this lovely explanation:
@AllArgsConstructor public class Parent { private String a; } public class Child extends Parent { private String b; @Builder public Child(String a, String b){ super(a); this.b = b; } }
As a result you can then use the generated builder like this:
Child.builder().a("testA").b("testB").build();
The official documentation explains this, but it doesn’t explicitly point out that you can facilitate it in this way.
I also found this works nicely with Spring Data JPA.
Upvotes: 30
Reputation: 34462
This is not possible in Lombok. Although it would be a really nice feature, it requires resolution to find the constructors of the super class. The super class is only known by name the moment Lombok gets invoked. Using the import statements and the classpath to find the actual class is not trivial. And during compilation you cannot just use reflection to get a list of constructors.
It is not entirely impossible but the results using resolution in val
and @ExtensionMethod
have taught us that is it hard and error-prone.
Disclosure: I am a Lombok developer.
Upvotes: 331