27

特定の画面のすべての基本パラメーターを定義するクラスがあります。ここから、アプリケーションのすべての画面が this のサブクラスになります。実装で変数の値を設定するには、すべての画面 (つまり、サブクラス)が必要です(つまり、各画面は、ナビゲーション ツリーのどのレベルにあるかを定義する必要があります)。

また、理想的には、この変数はfinalサブクラスで設定されている必要があります (これはおそらく不可能だと思います)。

これについて最善の方法は何ですか?Javaでこの種の動作を正しく強制する方法はありますか?

4

3 に答える 3

37

@pst のコメントは、この解決策につながります。

これは、変数では実行できません。しかし、抽象クラスは特定のメソッドが実装されていることを要求することができます: このメソッドは適切な値を返すことができます

変数を設定または返す関数を宣言するabstractことから、サブクラスにそれを正しく実装させることができます。

次に、外部クラスのすべてのサブクラスから関数を呼び出す必要があります。これは、外部クラスのどこかで実行する必要があることを意味します。これは、サブクラスの呼び出しを心配することなく、外部クラスの引数なしのコンストラクターで実行できますsuper

注: コンストラクターがスーパークラス コンストラクターを明示的に呼び出さない場合、Java コンパイラーは、スーパークラスの引数のないコンストラクターへの呼び出しを自動的に挿入します。スーパー クラスに引数のないコンストラクタがない場合、コンパイル時エラーが発生します。Object にはそのようなコンストラクターがあるため、Object が唯一のスーパークラスであれば問題はありません。 (Java ドキュメント: スーパー)

それに基づいて、このソリューションは持ちこたえ、次のいずれかである限り、変数を正しく強制的に設定します。

  1. スーパークラスでは他のコンストラクターは作成されません (したがって、代わりにサブクラスでスーパーを使用して別のコンストラクターを呼び出すことはできません)。
  2. スーパークラスの他のすべてのコンストラクターは、デフォルトのコンストラクターを内部的に呼び出します

コード:

スーパークラス:

public abstract class SuperClass {
    // Variable all inner classes must set
    static int myVar = 0;

    public SuperClass() {
        myVar = giveValue();
    }

    public abstract int giveValue();
}

サブクラス:

public class SubClass extends SuperClass {

    @Override
    public int giveValue() {
        return 5; // individual value for the subclass
    }

}
于 2013-02-22T03:04:08.193 に答える
13

子クラスインスタンスがフィールドを初期化するように強制するのではなく、親クラスコンストラクターに、初期化するフィールドを提供するインターフェイスを実装するパラメーターを取得させることで、構成の戦略に従うことができます。

class Screen {
  final Configuration config;
  Screen(Configuration config) {
    this.config = config;
  }
  // or
  Screen(ConfigFactory configFactory) {
    this.config = configFactory.make();
  }
}

interface ConfigFactory {
  Configuration make();
}

抽象メソッドの実装を使用するなど、構成を初期化するサブクラスインスタンスを要求しないように注意します。親クラスコンストラクターでの割り当ては、サブクラスインスタンスが初期化される前に行われ、構成の適切な計算を暗黙的に静的にします。

計算が静的でない場合、あなたをフォローしている開発者(またはメモリが完全でない場合は自分自身)によるnull参照またはNullPointerExceptionsのリスクがあります。共同作業者(および自分自身)の作業を容易にし、制約を明示的にします。

于 2013-02-22T02:23:56.443 に答える