为什么不抽象领域?

Pau*_*ers 92 java methods field abstract

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

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

为什么我不能开始抽象领域?Java可以设计为允许这样吗?

rsp*_*rsp 92

您可以通过在抽象类中使用在其构造函数中初始化的最终字段(未经测试的代码)来执行您所描述的操作:

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您的子类"忘记"通过超级构造函数初始化final,编译器将发出错误警告,就像未实现抽象方法时一样.

  • "编译器会发出警告".实际上,Child构造函数会尝试使用不存在的noargs构造函数,这是一个编译错误(不是警告). (4认同)
  • 很好的答案 - 这对我有用.我知道它已经发布了一段时间,但认为`Base`需要被声明为`abstract`. (3认同)
  • 我仍然不喜欢这种方法(即使这是唯一的方法),因为它为构造函数添加了一个额外的参数。在网络编程中,我喜欢创建消息类型,每个新消息都实现一种抽象类型,但必须具有唯一的指定字符,例如AcceptMessage的'A'和LoginMessage的'L'。这些确保自定义消息协议将能够将该区别字符放在线路上。这些对于类是隐式的,因此最好将它们用作字段,而不是传递给构造函数的东西。 (2认同)

Fel*_*ing 7

我认为没有任何意义.您可以将该函数移动到抽象类,只需覆盖一些受保护的字段.我不知道这是否适用于常量,但效果是一样的:

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你的观点是你要强制实现/覆盖/ errorMsg子类中的任何东西?我以为你只是想在基类中使用该方法,然后不知道如何处理该字段.

  • @felix,*enfor*和*contract*之间存在差异.这整篇文章以抽象类为中心,而抽象类又代表了必须由任何子类实现的契约.所以,当我们谈论有一个抽象字段时,我们说任何子类**必须**按合同实现该字段的值.你的方法并不能保证任何价值,也没有像合约那样明确表达预期的结果.非常非常不同. (8认同)
  • 说`protected String errorMsg;`不*强制你在子类中设置值. (6认同)
  • 好吧,我当然可以这样做.我想到了它.但是,当我知道我要在每个派生类中覆盖该值时,为什么我必须在基类中设置一个值?您的论证也可以用来证明允许抽象方法没有价值. (4认同)