为什么Java类不能像抽象类那样具有抽象字段?
例如:我有两个扩展同一个抽象基类的类。这两个类各自具有相同的方法,但其中包含String常数(恰好是错误消息)。如果字段可以是抽象的,那么我可以使这个常量抽象,并将该方法引入基类。相反,我必须创建一个抽象方法(getErrMsg()
在这种情况下称为该方法),该方法返回String,在两个派生类中重写此方法,然后可以拉出该方法(现在称为抽象方法)。
为什么我不能仅将字段抽象化?Java是否可以设计成允许这样做?
为什么Java类不能像抽象类那样具有抽象字段?
例如:我有两个扩展同一个抽象基类的类。这两个类各自具有相同的方法,但其中包含String常数(恰好是错误消息)。如果字段可以是抽象的,那么我可以使这个常量抽象,并将该方法引入基类。相反,我必须创建一个抽象方法(getErrMsg()
在这种情况下称为该方法),该方法返回String,在两个派生类中重写此方法,然后可以拉出该方法(现在称为抽象方法)。
为什么我不能仅将字段抽象化?Java是否可以设计成允许这样做?
Answers:
您可以通过在抽象类中的final字段中初始化其构造函数(未经测试的代码)来完成您描述的操作:
abstract class Base {
final String errMsg;
Base(String msg) {
errMsg = msg;
}
abstract String doSomething();
}
class Sub extends Base {
Sub() {
super("Sub message");
}
String doSomething() {
return errMsg + " from something";
}
}
如果您的子类“忘记”通过超级构造函数初始化最后一个,则编译器将发出警告错误,就像未实现抽象方法时一样。
Base
需要声明abstract
。
我认为没有任何意义。您可以将函数移至抽象类,并覆盖某些受保护的字段。我不知道这是否适用于常量,但是效果是一样的:
public abstract class Abstract {
protected String errorMsg = "";
public String getErrMsg() {
return this.errorMsg;
}
}
public class Foo extends Abstract {
public Foo() {
this.errorMsg = "Foo";
}
}
public class Bar extends Abstract {
public Bar() {
this.errorMsg = "Bar";
}
}
因此,您的意思是您想errorMsg
在子类中实施/覆盖/执行什么?我以为您只是想在基类中使用该方法,然后不知道该如何处理该字段。
protected String errorMsg;
哪些以某种方式强制设置子类中的值。它类似于实际上将所有方法实现为占位符的抽象类,以便开发人员尽管不需要每个方法,也不必实现每个方法。
protected String errorMsg;
也不会强制您设置在子类中的价值。
显然,它本来可以允许这样做的,但是在幕后,它仍然必须进行动态分配,因此需要进行方法调用。Java的设计(至少在早期)是在某种程度上试图做到极简。就是说,如果语言中已经存在的其他功能可以轻松地模拟它们,那么设计人员将避免添加新功能。
阅读标题,我认为您是指抽象实例成员。我看不出它们有什么用。但是抽象静态成员完全是另一回事。
我经常希望我可以在Java中声明一个类似于以下内容的方法:
public abstract class MyClass {
public static abstract MyClass createInstance();
// more stuff...
}
基本上,我想坚持认为,父类的具体实现提供了带有特定签名的静态工厂方法。这将使我可以引用一个具体的类,Class.forName()
并确定可以按照自己的选择构造一个类。
@autowired T fieldName
。如果将if T
定义为T extends AbstractController
,则类型擦除会导致该字段作为type生成,AbstractController
并且不能自动连接,因为它不是具体的也不是唯一的。我通常同意它们没有太多用处,因此它们不属于该语言。我不同意的是它们没有用。
另一种选择是在基类中将该字段定义为公共字段(如果需要,可以将其定义为final),然后根据当前使用的子类在基类的构造函数中初始化该字段。这有点阴暗,因为它引入了循环依赖。但是,至少它不是一个可以改变的依赖项-即,子类将存在或不存在,但是子类的方法或字段不会影响的值field
。
public abstract class Base {
public final int field;
public Base() {
if (this instanceof SubClassOne) {
field = 1;
} else if (this instanceof SubClassTwo) {
field = 2;
} else {
// assertion, thrown exception, set to -1, whatever you want to do
// to trigger an error
field = -1;
}
}
}