如何强制子类在java中设置变量?

2022-09-01 15:24:46

我有一个类,它定义了给定屏幕的所有基本参数。从这里开始,应用程序中的每个屏幕都是它的子类。我需要每个屏幕(即子类)在其实现中设置变量的值(即,每个屏幕必须定义它在导航树中的级别)。

此外,理想情况下,这个变量应该是在子类中设置它的时候(我意识到这可能是不可能的)。final

最好的方法是什么?有没有办法在Java中正确实施这种类型的行为?


答案 1

@pst的评论导致了这个解决方案。

这不能用变量来完成。但是抽象类可以要求实现特定方法:此方法可以返回适用的值

通过声明函数来设置或返回变量,您可以强制任何子类正确实现它。abstract

接下来,该函数必须由外部类的每个子类调用。这意味着它必须在外部类中的某个位置完成。这可以在外部类的无参数构造函数中完成,而不必担心子类调用:super

注: 如果构造函数未显式调用超类构造函数,Java 编译器会自动插入对超类的无参数构造函数的调用。如果超类没有无参数构造函数,您将收到编译时错误。对象确实有这样的构造函数,所以如果对象是唯一的超类,那就没有问题了。(Java docs: Super)

基于此,此解决方案将保持并正确强制设置变量,只要:

  1. 在超类中不会创建其他构造函数(因此不能在子类中使用 super 来调用不同的构造函数)
  2. 超类中的所有其他构造函数仍在内部调用默认构造函数

代码:

超类:

public abstract class SuperClass {
    // Variable all inner classes must set
    static int myVar = 0;

    public SuperClass() {
        myVar = giveValue();
    }

    public abstract int giveValue();
}

亚纲:

public class SubClass extends SuperClass {

    @Override
    public int giveValue() {
        return 5; // individual value for the subclass
    }

}

答案 2

与其强制子类实例初始化字段,不如遵循组合策略,让父类构造函数采用一个参数来实现一个接口,该接口提供您希望初始化的字段。

class Screen {
  final Configuration config;
  Screen(Configuration config) {
    this.config = config;
  }
  // or
  Screen(ConfigFactory configFactory) {
    this.config = configFactory.make();
  }
}

interface ConfigFactory {
  Configuration make();
}

我提醒不要要求子类实例初始化配置,例如使用抽象方法实现。父类构造函数中的赋值在子类实例初始化之前发生,从而隐式地使配置的正确计算成为静态的。

如果计算不是静态的,则存在以下开发人员(或者如果您的内存不完美,则为您自己的)的空引用或 NullPointerExceptions 的风险。让您的协作者(和您自己)更轻松,并使约束明确。


推荐