12

Java プログラムには、親 (抽象) から継承する複数のサブクラスがあります。すべての子には、一度だけ設定されるメンバーが必要であることを表現したかった (これは、コンストラクターから実行する予定でした)。私の計画はs.thをコーディングすることでした。このような:

public abstract class Parent {
    protected final String birthmark;
}

public class Child extends Parent {
    public Child(String s) {
        this.birthmark = s;
    }
}

しかし、これは Java の神々を喜ばせていないようです。親クラスではbirthmark「初期化されていない可能性があります」というメッセージが表示され、子クラスでは「最終フィールドbirthmarkにアクセスできません」というメッセージが表示されます。

では、これに対するJavaの方法は何ですか? 私は何が欠けていますか?

4

8 に答える 8

20

親クラスを比較している間、コンパイラはサブクラスがそれを初期化することを確認できないため、それを行うことはできません。親のコンストラクターで初期化し、子に親のコンストラクターを呼び出させる必要があります。

public abstract class Parent {
    protected final String birthmark;
    protected Parent(String s) {
        birthmark = s;
    }
}

public class Child extends Parent {
    public Child(String s) {
        super(s);
        ...
    }
}
于 2009-03-19T18:48:42.923 に答える
7

親コンストラクターに渡します。

public abstract class Parent {
    private final String birthmark;
    public Parent(String s) {
        birthmark = s;
    }
}

public class Child extends Parent {
    public Child(String s) {
        super(s);
    }
}
于 2009-03-19T18:48:31.647 に答える
2

これを行うもう 1 つの Java 的な方法は、おそらく、親クラスに抽象「ゲッター」を定義させ、子クラスにそれを実装させることです。この場合、それを行うのは良い方法ではありませんが、場合によっては、まさにあなたが望むものになる可能性があります。

于 2009-03-19T18:49:24.420 に答える
1

初期化をメソッドに委譲してみませんか。次に、親クラスのメソッドをオーバーライドします。

public class Parent {
   public final Object x = getValueOfX();
   public Object getValueOfX() {
      return y;
   }
}
public class Child {
  @Override
  public Object getValueOfX() {
     // whatever ...
  }
}

これにより、カスタムの初期化が可能になります。

于 2009-03-19T18:50:19.940 に答える
0

はい、最終的なメンバーは、それらが宣言されているクラスに割り当てられます。String 引数を持つコンストラクターを Parent に追加する必要があります。

于 2009-03-19T18:49:28.553 に答える
0

サブクラスによって呼び出されるスーパークラスでコンストラクターを宣言します。スーパークラスでフィールドを設定して、フィールドが初期化されていることを確認する必要があります。そうしないと、コンパイラはフィールドが初期化されていることを確認できません。

于 2009-03-19T18:49:56.930 に答える
0

Parent クラスで final が常に初期化されるように、おそらく Parent(Stringあざ) コンストラクターが必要です。次に、 Child() コンストラクターから super(birthmark) を呼び出すことができます。

于 2009-03-19T18:50:01.377 に答える