我有一个抽象类,我希望所有子类根据实现来定义一个常量 - 它主要是关于类实现的元数据。
在超类中:
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";
有没有办法强制类的实现声明一个常量?
答案 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界面中声明字段时,它隐含了修饰符public
,static
和final
。未来对Java Programming Language MIGHT的更改允许添加abstract
,从而制作隐含的修饰符public abstract static final String USER_FRIENDLY_NAME;
,但是当您可以清楚地为此定义规则时,使用单词abstract
会让人感到困惑,因为abstract
和final
通常被理解为定义相反的含义。
我正在指责未来版本的Java将实现这一点。我听说私有接口方法将在Java 9中添加(用于默认方法之间),但是对于语言的这种添加还没有任何说法。我敢肯定,首先要考虑一些向后兼容性问题。如果来自甲骨文的任何人都读到这个,请让我们在接口处让我们宣布继承并让我们继续进行定义/接口定义他们!
与此同时,您唯一的选择是在您的界面或抽象类中定义String getUserFriendlyName();
方法。不那么优雅,也许不那么有效,但你目前没有别的选择。