繁体   English   中英

强制子类在抽象 java 类中包含常量

[英]force subclasses to include constant in abstract java class

我有一个抽象类,我希望所有子类都根据实现定义一个常量——它主要是关于类实现的元数据。

在超类中:

protected static final String OBJECT_NAME;
protected static final String OBJECT_DEF;

然后在子类中:

protected static final String OBJECT_NAME = "awesome class";
protected static final String OBJECT_DEF = "an awesome class that is also great";

有没有办法强制类的实现声明一个常量?

您可以强制子类定义一个方法,该方法可以是该类的常量。

protected abstract String objectName();
protected abstract String objectDef();

注意:如果您有子类的子类,它们可能会“忘记”覆盖这些方法。

也可以选择一个接口,因为您没有超类的合理默认值:

interface HasObjectNameAndDef {
    public String getObjectName();
    public String getObjectDef(); 
}

然后让您的实际类实现接口。 作为奖励,您将获得更灵活的测试。

这是另一种方法。 我喜欢它,因为它很严格,让我们可以将大部分代码(包括 getter)放入父类中,使其子类保持整洁。

abstract class Parent {
    private final int age;
    private final String name;

    Parent(int age, String name) {
        this.age = age;
        this.name = name;
    }

    int getAge() {
        return age;
    }
}

class Child extends Parent {

    Child() {
        super(18, "John");
        // any other Child specific constructor logic
    }
}

class Main {
    public static void main(String[] args) {
        var child = new Child();
        System.out.println(child.getAge()); // Will print 18
    }
}

注意: Child不继承Parent的构造函数,因此在初始化Child时没有意外使用 wearg 构造函数的危险。

不,你不能。

你甚至不能在你的抽象超类中声明常量而不给它们分配具体的值。 在其他情况下,您将收到错误消息。 您应该在它们的声明期间或在类构造函数中初始化 final 字段。

您可以声明抽象方法来初始化您的变量(但这会更加混淆)。 像这样:

protected String OBJECT_NAME = getObjectNameValue();

public abstract String getObjectNameValue();

但在这种情况下,您的变量和方法不应该是静态的。 因为您不能将静态方法定义为抽象方法( 请看这里的解释)。

或者您可以直接使用方法而不是 Peter Lawrey 提出的变量,这将更具可读性。

这不会那样工作。 我将这些定义为抽象函数:

protected abstract String objectName();
protected abstract String objectDef();

在子类中:

private static final String OBJECT_NAME = "awesome class";
private static final String OBJECT_DEF = "bla";

protected String objectName(){
    return OBJECT_NAME;
}

protected String objectDef(){
    return OBJECT_DEF;
}

这些方法不是static ,但我认为这是最接近你想要的。

我知道你在说什么。

例如,我想要一个接口(我称之为 ExecutableList)有一个名为USER_FRIENDLY_NAME字符串字段

public interface ExecutableList<T extends ExecutableList<T,E>,E> //This is type parameter
    extends List<E>,                                             //self referencing. Trust
            Comparable<E>,                                       //me, it has its uses.
{
  /** This would declare a constant but leave it to sub-interfaces/classes to define it. */
  abstract String USER_FRIENDLY_NAME;

  //Define the rest of your interface

}

不幸的是,这在 Java 中是不可能的。 当您在 Java 接口中声明一个字段时,它意味着修饰符publicstaticfinal Java 编程语言的未来更改可能允许添加abstract ,从而使隐含修饰符public abstract static final String USER_FRIENDLY_NAME; 但是,虽然您可以为此明确定义规则,但使用abstract这个词会令人困惑,因为abstractfinal通常被理解为定义相反的含义。

我交叉手指,Java 的未来版本将实现这一点。 我听说将在 Java 9 中添加私有接口方法(用于在默认方法之间使用),但还没有关于该语言添加的消息。 我敢肯定,首先要考虑许多向后兼容性问题。 如果 Oracle 的任何人读到了这篇文章,请让我们在接口中声明常量并让继承类/接口定义它们!!!

与此同时,你唯一的选择是定义一个String getUserFriendlyName(); 接口或抽象类中的方法。 不那么优雅,也许也不那么高效,但目前您别无选择。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM