@Builder Lombok - 继承

@Builder Lombok - Inheritance

我尝试对具有注释 @SuperBuilder 的 class 使用继承。 我有一个超级class:

@SuperBuilder
@Data
public class BaseClass {
    private String userID;
    private String clientID;
}

还有两个 class 扩展 BaseClass:

@SuperBuilder
@Data
public class UserWithName extends BaseClass {
    private String name;
}

并且:

@SuperBuilder
@Data
public class UserWithNumber extends BaseClass {
    private int number;
}

之后,我尝试创建一些 BaseBuilder:

public BaseClass.BaseClassBuilder generateBaseBuilder() {
    return BaseClass.builder()
            .userID("1")
            .clientID("1");
}

我想在尝试为 classes UserWithNameUserWithNumber 创建对象时使用基础构建器。我试着这样做:

public UserWithName generateUserWithName(String name) {
    UserWithName.UserWithNameBuilder builder = (UserWithName.UserWithNameBuilder) generateBaseBuilder();
    return builder
            .name(name)
            .build();
}

但它不起作用 (ClassCastException)。这是完整的代码:

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();
    }
}

有没有什么方法可以使用我的方法 generateBaseBuilder() 创建我的对象?

您不能将 BaseClassBuilder 的实例转换为 UserWithNameBuilder,因为继承关系是相反的,因为它反映了带注释的 class 之间的关系:UserWithNameBuilder extends BaseClassBuilder,比如 UserWithName extends BaseClass.

因此,无法调用您要构建的 class 的 builder() 方法。

话虽如此,我猜您的 generateBaseBuilder() 方法的主要目的不是创建生成器,而是为新实例设置一些默认值。有两种方法可以实现:

  1. 向您的字段添加默认值(作为字段初始值设定项)并在其上添加 @Builder.Default

  2. 重写您的 generateBaseBuilder 方法,使其成为 setDefaultValues,它将构建器实例作为参数并仅设置这些值:

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();
}

我更喜欢第一个选项,因为它更简洁。但是,第二个选项更灵活,因为您可以有多个这样的 setValues 方法,每个方法都可以设置不同的值。

请注意,您还可以将 this/these 方法直接包含到 BaseClassBuilder 中。 Whosebug 上有一些讨论自定义 @SuperBuilder.

的问题和答案