为什么不抽象领域?

为什么Java类不能像抽象方法那样具有抽象字段?

例如:我有两个类扩展相同的抽象基类。 这两个类每个都有一个相同的方法,除了一个String常量,它们恰好是一个错误信息。 如果字段可能是抽象的,我可以使这个不变的抽象,并将方法拉入基类。 相反,我必须创build一个抽象方法,在这种情况下称为getErrMsg() ,它返回String,在两个派生类中重写此方法,然后可以调用抽象方法(现在称为抽象方法)。

为什么我不能把这个领域的摘要作为开始? Java可以devise成允许这个吗?

您可以通过在您的抽象类中创build一个在其构造函数中初始化的最终字段(未经testing的代码)来执行您所描述的内容:

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

如果您的子类“忘记”通过超级构造函数初始化最终的结果,那么编译器会给出错误警告 ,就像抽象方法没有实现时一样。

我看不出这点。 您可以将该函数移动到抽象类,并覆盖一些受保护的字段。 我不知道这是否适用于常量,但效果是一样的:

 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 ? 我以为你只是想在基础类的方法,并不知道如何处理领域。

显然它可能被devise为允许这样做,但在封面之下,它仍然需要做dynamic调度,因此是一个方法调用。 Java的devise(至less在早期)在某种程度上是一种极简主义的尝试。 也就是说,devise人员试图避免添加新的function,如果可以用语言中已有的其他function轻松地进行模拟。

读你的标题,我以为你是指抽象实例成员; 我看不到他们有太多的用处。 但抽象的静态成员完全是另一回事。

我经常希望能够在Java中声明如下的方法:

 public abstract class MyClass { public static abstract MyClass createInstance(); // more stuff... } 

基本上,我想坚持我的父类的具体实现提供具有特定签名的静态工厂方法。 这将允许我通过Class.forName()获得对具体类的引用,并确保可以按照我select的约定构造一个类。

另一个select是将该字段定义为基类中的public(final,如果你喜欢),然后根据当前正在使用的子类在基类的构造函数中初始化该字段。 这有点不好意思,因为它引入了循环依赖。 但是,至less它不是一个可以改变的依赖关系,即子类可能存在或者不存在,但子类的方法或者域不能影响域的价值。

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

你可以在抽象类中定义一个参数化的构造函数。

这样,子类被迫定义自己的构造函数,并调用超级构造函数,如下所示:

 public abstract class TransactionManager { private String separator; public TransactionManager(String separator) { this.separator = separator; } } 

那么你的具体类将如下所示:

 public class TransactionManagerFS extends TransactionManager{ // The IDE forces you to implement constructor. public TransactionManagerFS(String separator) { super(separator); } } 

从这里查看完整的示例。