Reputation: 150
I try to use inheritance for my class that has annotation @SuperBuilder
.
I have one superclass:
@SuperBuilder
@Data
public class BaseClass {
private String userID;
private String clientID;
}
And two classes that extend BaseClass
:
@SuperBuilder
@Data
public class UserWithName extends BaseClass {
private String name;
}
And:
@SuperBuilder
@Data
public class UserWithNumber extends BaseClass {
private int number;
}
After that, I try to create some BaseBuilder
:
public BaseClass.BaseClassBuilder generateBaseBuilder() {
return BaseClass.builder()
.userID("1")
.clientID("1");
}
And I want to use the base builder when I try to create my objects for classes UserWithName
and UserWithNumber
. I tried to do that something like that:
public UserWithName generateUserWithName(String name) {
UserWithName.UserWithNameBuilder builder = (UserWithName.UserWithNameBuilder) generateBaseBuilder();
return builder
.name(name)
.build();
}
But it doesn't work (ClassCastException
). Here is the full code:
public class Main {
@SuperBuilder
@Data
public static class BaseClass {
private String userID;
private String clientID;
}
@SuperBuilder
@Data
public static class UserWithName extends BaseClass {
private String name;
}
@SuperBuilder
@Data
public static class UserWithNumber extends BaseClass {
private int number;
}
public BaseClass.BaseClassBuilder generateBaseBuilder() {
return BaseClass.builder()
.userID("1")
.clientID("1");
}
public UserWithName generateUserWithName(String name) {
UserWithName.UserWithNameBuilder builder = (UserWithName.UserWithNameBuilder) generateBaseBuilder();
return builder
.name(name)
.build();
}
}
Is there some way how I can use my method generateBaseBuilder()
for creating my objects?
Upvotes: 0
Views: 592
Reputation: 8042
You cannot cast an instance of BaseClassBuilder
to UserWithNameBuilder
, because the inheritance relation is in the opposite direction, as it reflects the relation between the annotated classes: UserWithNameBuilder extends BaseClassBuilder
, like UserWithName extends BaseClass
.
Thus, there is no way around calling the builder()
method of the very class you want to build.
That being said, I guess that the primary purpose of your generateBaseBuilder()
method is not to create the builder, but to set some default values for the new instances. There are two ways to achieve this:
Add default values (as field initializers) to your fields and put a @Builder.Default
on them.
Rewrite your generateBaseBuilder
method to become setDefaultValues
that takes a builder instance as parameter and only sets those values:
public static <T extends BaseClass.BaseClassBuilder<?, ?>> T setDefaultValues(T builder) {
builder
.userID("1")
.clientID("1");
return builder;
}
public static UserWithName generateUserWithName(String name) {
UserWithNameBuilder<?,?> builder = setDefaultValues(UserWithName.builder());
return builder
.name(name)
.build();
}
I'd prefer the first option because it is more concise. However, the second option is more flexible, as you can have multiple of those setValues methods, each of which could set different values.
Note that you could also include this/these method(s) directly into the BaseClassBuilder
. There are a few questions and answers here at StackOverflow that discuss customizing @SuperBuilder
.
Upvotes: 2