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

时间:2012-08-10 07:07:25

标签: java inheritance constants

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

在超类中:

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

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

6 个答案:

答案 0 :(得分:10)

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

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

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

答案 1 :(得分:1)

不妨选择界面,因为你没有超类的合理默认值:

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

让你的实际类实现接口。你会更容易测试是一种奖励。

答案 2 :(得分: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的构造函数,因此在初始化Child时不存在意外使用wearg构造函数的危险。

答案 3 :(得分:0)

没有。你不能。

如果没有为具体值赋值,您甚至无法在抽象超类中声明常量。在其他情况下,您将收到错误。您应该在声明期间或在类构造函数中初始化最终字段。

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

protected String OBJECT_NAME = getObjectNameValue();

public abstract String getObjectNameValue();

但在这种情况下,您的变量和方法不应该是静态的。因为您不能将静态方法定义为abstract(look here for explanation)。

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

答案 4 :(得分:0)

这不会那样。我将它们定义为抽象函数:

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

答案 5 :(得分:-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 Programming Language MIGHT的更改允许添加abstract,从而制作隐含的修饰符public abstract static final String USER_FRIENDLY_NAME;,但是当您可以清楚地为此定义规则时,使用单词abstract会让人感到困惑,因为abstractfinal通常被理解为定义相反的含义。

我正在指责未来版本的Java将实现这一点。我听说私有接口方法将在Java 9中添加(用于默认方法之间),但是对于语言的这种添加还没有任何说法。我敢肯定,首先要考虑一些向后兼容性问题。如果来自甲骨文的任何人都读到这个,请让我们在接口处让我们宣布继承并让我们继续进行定义/接口定义他们!

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