14

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

在超类中:

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";

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

4

6 回答 6

12

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

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

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

于 2012-08-10T07:17:12.677 回答
1

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

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,但我认为这是最接近你想要的方法。

于 2012-08-10T07:24:26.637 回答
1

最好选择一个接口,因为您对超类没有合理的默认值:

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

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

于 2012-08-10T07:39:26.813 回答
1

这是另一种方法。我喜欢它,因为它很严格,允许我们将大部分代码(包括 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的构造函数,因此在初始化时不存在意外使用 wearg 构造函数的危险Child

于 2020-03-03T13:29:53.303 回答
0

不,你不能。

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

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

protected String OBJECT_NAME = getObjectNameValue();

public abstract String getObjectNameValue();

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

或者您可以像 Peter Lawrey 建议的那样直接使用方法而不是变量,这将更具可读性。

于 2012-08-10T07:13:11.893 回答
-1

我知道你在说什么。

例如,我想要一个接口(我称之为 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会令人困惑,因为abstract通常final理解为定义相反的含义。

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

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

于 2015-07-24T22:07:02.927 回答