提问人:Y.F. 提问时间:9/20/2023 更新时间:9/27/2023 访问量:79
可以使用 abtract 方法初始化抽象基类中的最终成员吗?
Is it ok to initialize final member in abstract base class using abtract method?
问:
我想知道我是否可以使用由 abtract 方法实现的 abtract 方法的结果初始化抽象基类中的最后一个字段。 我知道派生的 ctor 会首先调用基 ctor,所以我保证 abtract 方法的实现也只依赖于派生类的声明中定义的最终字段。 我尝试以下代码,它似乎有效。
abstract class Base {
protected final String name = calName();
protected abstract String calName();
}
public final class Foo extends Base {
private final String id = "42";
@Override
protected String calName() {
return String.format("WithId%s", id);
}
public void display() {
System.out.printf("name: %s\n", name);
System.out.printf("id: %s\n", id);
}
public static void main(String[] args) {
var foo = new Foo();
foo.display();
}
}
那么这是 java 中的合法操作,还是一个非常糟糕的主意?
答:
0赞
Nolequen
9/20/2023
#1
不,这是不行的。
在对象构造过程中调用抽象方法(以及任何类型的可重写方法)是一个坏主意。
此类调用可能会导致细微的错误,因为对象初始化可能会在方法调用之前发生。
0赞
Y.F.
9/27/2023
#2
感谢您的所有意见。现在我对如何处理这种情况有了一定的了解。
如果可以使用默认 ctor 直接构造该字段并在以后进行配置,则我可以在基类中将其构造为最终字段,并在派生构造阶段对其进行配置:
abstract class Base { protected final Widget core = new Widget(); public void methodThatUsesCore() { core.display(); } } public final class Foo42 extends Base { { core.configure(42, "jklmn"); } }
如果必须使用派生类提供的信息来构造该字段,我应该将其放入派生类中,并在基类中添加一个抽象 getter:
abstract class Base { protected abstract Widget getCore(); public void methodThatUsesCore() { getCore().display(); } } public final class Foo42 extends Base { private final Widget core = new Widget(42, "jklmn"); @Override protected Widget getCore() { return core; } }
这是一个合理的设计吗?
评论
id
Foo
protected final String name
calName()