114

抽象メソッドのように Java クラスに抽象フィールドを持たせないのはなぜですか?

例: 同じ抽象基本クラスを拡張する 2 つのクラスがあります。これらの 2 つのクラスには、エラー メッセージである String 定数を除いて、同じメソッドが含まれています。フィールドを抽象化できる場合は、この定数を抽象化し、メソッドを基本クラスにプルアップできます。代わりに、この場合は String を返す抽象メソッドを作成getErrMsg()し、2 つの派生クラスでこのメソッドをオーバーライドする必要があります。その後、メソッド (現在は抽象メソッドを呼び出します) をプルアップできます。

そもそもフィールドを抽象化できなかったのはなぜですか? Java はこれを可能にするように設計されているでしょうか?

4

5 に答える 5

114

コンストラクターで初期化される抽象クラスに 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";
    }
}

子クラスがスーパー コンストラクターを介して final を初期化するのを「忘れた」場合、コンパイラは、抽象メソッドが実装されていない場合と同様に、エラーを警告します。

于 2010-02-05T22:59:31.477 に答える
9

それには何の意味もありません。関数を抽象クラスに移動して、保護されたフィールドをオーバーライドするだけです。これが定数で機能するかどうかはわかりませんが、効果は同じです:

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つまり、サブクラスで実装/オーバーライド/その他を強制したいということですか? 基本クラスにメソッドが必要なだけで、フィールドの処理方法がわからなかったと思いました。

于 2010-02-05T22:56:24.243 に答える
4

明らかに、これを許可するように設計されている可能性がありますが、内部では依然として動的ディスパッチを実行する必要があり、したがってメソッド呼び出しが必要です。Java の設計 (少なくとも初期の頃) は、ある程度、ミニマリストを目指したものでした。つまり、設計者は、言語にすでに含まれている他の機能によって簡単にシミュレートできる場合、新しい機能を追加することを避けようとしました。

于 2010-02-05T22:53:21.637 に答える
0

あなたのタイトルを読んで、抽象的なインスタンスメンバーについて言及していると思いました。そして、それらの用途はあまり見られませんでした。しかし、抽象静的メンバーはまったく別の問題です。

Java で次のようなメソッドを宣言できたらいいのにとよく思います。

public abstract class MyClass {

    public static abstract MyClass createInstance();

    // more stuff...

}

基本的に、親クラスの具体的な実装は、特定の署名を持つ静的ファクトリ メソッドを提供することを主張したいと思います。これにより、具象クラスへの参照を取得Class.forName()でき、選択した規則で確実に構築できるようになります。

于 2010-02-05T22:58:53.683 に答える
0

もう 1 つのオプションは、基本クラスでフィールドを public (必要に応じて 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;
    }
  }
}
于 2017-06-16T15:33:01.263 に答える