Lombok调用子类函数以使用默认构造器生成器

4

我有两个类,父类需要在构建时从子类中获取一些属性。是否有一种方式可以使用lombok builders来支持这一点?

Parent.java

import lombok.Builder;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

@Getter
@SuperBuilder
public abstract class Parent {
    @Builder.Default
    private String requestType = getRequestTypeFromSubclass();
    abstract String getRequestTypeFromSubclass();
}

Child.java

import lombok.Builder;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

import java.util.List;

@Getter
@SuperBuilder
public class Child extends Parent {
    @Override
    String getRequestTypeFromSubclass() {
        return "Child1";
    }
}


上述代码在编译时出现错误,错误信息如下:
非静态方法getRequestType()无法从静态上下文@SuperBuilder引用。

这是一个问题一直落到了一个问题,即Java是否应该有“抽象静态”方法。我认为像这样的情况证明了这个概念,但Java的一般前提似乎仍然是“多态性是对象派生的特征,而不是类派生的特征”。(还不是答案,但我会检查)。 - TreffnonX
以上内容并非日常使用,其中一个用例是在进行Jackson序列化时。子类是根据requestType键选择的。 - best wishes
3个回答

1

Baeldung建议的那样,使用toBuilder=true并移除@Builder.Default

import lombok.Getter;
import lombok.experimental.SuperBuilder;

@Getter
@SuperBuilder(toBuilder=true)
public abstract class Parent {

    private String requestType = getRequestType();
    abstract String getRequestType();
}

有了这个,我们可以摆脱双重初始化

使用toBuilder调用构建器进行更改,子项:

import lombok.Getter;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder
public class Child extends Parent {
    @Override
    String getRequestType() {
        return "Child1";
    }
    public static void main(String[] args) {
        Child child = Child.builder().build();
        System.out.println(child.getRequestType());
    }
}

1
@TreffnonX 什么是 defineRequestType()?你移除了 @Builder.Default 吗? - user7294900
我忘记在defineRequestType上删除@Builder.Default。因此,代码现在在运行时失败了。@Test public void test_lombokBuilderPolymorphism() { Child child1 = Child.builder().build(); assertEquals("child1", child1.getRequestType()); }的测试用例在断言处失败:expected: <child1> but was:<null> - TreffnonX
改为 new Child().toBuilder().build() - user7294900
是的,对我来说这个不起作用。没有.toBuilder()方法。@user7294900,请您发布父级和子级两者吗? - best wishes
@bestwishes 添加了子节点和父节点。 - user7294900
显示剩余2条评论

0

虽然Lombok是一个很棒的工具,但在这种情况下,您可能希望避免使用构建器模式。您想要的效果(在父类初始化时访问子类方法)可以在标准POJO构造函数中实现。以下代码对我有效:

@Getter
public abstract class Parent {
    private String requestType = defineRequestType();

    protected abstract String defineRequestType();
}


@Getter
public class Child extends Parent {
    protected String defineRequestType() {
        return "child1";
    }
}

以及以下测试用例:

@Test
public void test_lombokBuilderPolymorphism() {
    Child child1 = new Child();
    assertEquals("child1", child1.getRequestType());
}

所以,除非你有其他原因需要使用构建器模式,否则默认的POJO功能似乎已经足够了。

顺便说一下:你应该给定义方法命名为除get...之外的其他名称,这样它就不会与生成的getter(getRequestType)冲突。


0

Builder.Default 定义在静态作用域中,表达式可能无法解析抽象方法的实现。

也许您想尝试这个:

@Getter
@SuperBuilder
public abstract class Parent {

    private String reqType;
    abstract String getRequestType();

    public String getReqType() {
        return Objects.isNull(reqType) ? getRequestType() : reqType;
    }
}

通过使用不同于实际属性获取方法的方法名称覆盖属性方法,应该可以解决该问题。

尝试使用:

Parent parent = Child.builder().build();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接