web-dev-qa-db-ja.com

クラスのサブクラスのフィールドを上書きすると、サブクラスには同じ名前(および異なるタイプ)の2つのフィールドがありますか?

3つのクラスがあります。

public class Alpha {
    public Number number;
}

public class Beta extends Alpha {
    public String number;
}

public class Gama extends Beta {
    public int number;
}

次のコードがコンパイルされるのはなぜですか?そして、なぜランタイムエラーなしでテストが合格するのですか?

@Test
public void test() {
    final Beta a = new Gama();
    a.number = "its a string";
    ((Alpha) a).number = 13;
    ((Gama) a).number = 42;

    assertEquals("its a string", a.number);
    assertEquals(13, ((Alpha) a).number);
    assertEquals(42, ((Gama) a).number);
}
49
fiction

メンバー変数はメソッドのようにオーバーライドできません。クラスnumberおよびBetaGama変数は、スーパークラスのメンバー変数numberの-​​非表示(オーバーライドではない)です。

キャストすることにより、スーパークラスの非表示のメンバーにアクセスできます。

67
Jesper

フィールドをオーバーライドにすることはできません。そもそも多態的にアクセスされることはありません。それぞれの場合に新しいフィールドを宣言するだけです。

いずれの場合も、式のコンパイル時のタイプは、whichnumberというフィールドを意味するのに十分であるため、コンパイルされます。

実際のプログラミングでは、次の2つの方法でこれを回避します。

  • 常識:フィールドをシャドウイングするとコードが読みにくくなるので、やらないでください
  • 可視性:すべてのフィールドをプライベートにすると、サブクラスはとにかくそれらを知りません
44
Jon Skeet