[英]How to ensure that child class will call the correct super constructor in lombok?
[英]how to Call super constructor in Lombok
我有一堂課
@Value
@NonFinal
public class A {
int x;
int y;
}
我還有一個B班
@Value
public class B extends A {
int z;
}
lombok 拋出錯誤,說它找不到 A() 構造函數,顯式調用它我想讓 lombok 做的是給 b 類注釋,以便它生成以下代碼:
public class B extends A {
int z;
public B( int x, int y, int z) {
super( x , y );
this.z = z;
}
}
我們在龍目島有注釋可以做到這一點嗎?
這在龍目島是不可能的。 盡管這將是一個非常好的功能,但它需要解析才能找到超類的構造函數。 只有在調用 Lombok 時才知道超類的名稱。 使用導入語句和類路徑來查找實際類並非易事。 在編譯期間,您不能僅使用反射來獲取構造函數列表。
這並非完全不可能,但在val
和@ExtensionMethod
使用分辨率的結果告訴我們,這很難且容易出錯。
披露:我是龍目島的開發人員。
Lombok Issue #78引用此頁面https://www.donneo.de/2015/09/16/lomboks-builder-annotation-and-inheritance/並附有這個可愛的解釋:
@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; } }
因此,您可以像這樣使用生成的構建器:
Child.builder().a("testA").b("testB").build();
官方文檔對此進行了解釋,但並沒有明確指出您可以通過這種方式為其提供便利。
我還發現這與 Spring Data JPA 配合得很好。
Lombok 1.18 版引入了@SuperBuilder 注釋。 我們可以使用它以更簡單的方式解決我們的問題。
您可以參考https://www.baeldung.com/lombok-builder-inheritance#lombok-builder-and-inheritance-3 。
因此,在您的子類中,您將需要這些注釋:
@Data
@SuperBuilder
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
在您的父類中:
@Data
@SuperBuilder
@NoArgsConstructor
Lombok 不支持通過將任何@Value
注釋類@Value
final
(如您所知,使用@NonFinal
)來表示。
我發現的唯一解決方法是自己將所有成員聲明為 final 並改用@Data
注釋。 這些子類需要由@EqualsAndHashCode
注釋,並且需要一個顯式的 all args 構造函數,因為 Lombok 不知道如何使用超類中的 all args 創建一個:
@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;
}
}
尤其是子類的構造函數,對於成員眾多的超類來說,解決方案顯得有些凌亂,抱歉。
對於具有許多成員的超類,我建議您使用 @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;
}
}
如果子類的成員多於父類,則可以做得不是很干凈,但方法很短:
@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;
}
}
作為一個選項,您可以使用com.fasterxml.jackson.databind.ObjectMapper
從父類初始化子類
public class A {
int x;
int y;
}
public class B extends A {
int z;
}
ObjectMapper MAPPER = new ObjectMapper(); //it's configurable
MAPPER.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
MAPPER.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
//Then wherever you need to initialize child from parent:
A parent = new A(x, y);
B child = MAPPER.convertValue( parent, B.class);
child.setZ(z);
如果需要,您仍然可以在 A 和 B 上使用任何lombok
注釋。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.