java 在抽象基类中使用abtract方法初始化final成员可以吗?

alen0pnh  于 2023-09-29  发布在  Java
关注(0)|答案(2)|浏览(87)

我想知道我是否可以用一个抽象基类的提取方法的结果初始化一个final字段,这将由派生类实现。我知道派生的ctor会先调用基类ctor,所以我保证abtract方法的实现也只依赖于派生类的声明时定义的final字段。我尝试了下面的代码,它似乎工作。

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中是一个合法的行为,还是一个非常糟糕的主意?

gopyfrb3

gopyfrb31#

不,这不好。
在对象构造期间调用抽象方法(以及任何类型的可重写方法)是一个坏主意。
这样的调用可能会导致细微的bug,因为对象初始化可能发生在方法调用之前。

pieyvz9o

pieyvz9o2#

谢谢你的意见。现在我对如何处理这种情况有了一些想法。
1.如果字段可以直接使用默认的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");
     }
 }

1.如果必须用派生类提供的信息来构造字段,我应该把它放到派生类中,并在基类中添加一个抽象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; }
 }

这是一个合理的设计?

相关问题