18

以下は、プロジェクトのコードの一部です。

public class Body extends Point{
    public double x, y, mass;

    public Body() {
        x = y = mass = 0;
    }

    public Body(double x, double y, double mass) {
        this.mass = mass;
        this.x = x;
        this.y = y;
    }
}

public class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

これを行うと、Body クラス内に x という2 つの変数が作成され、Body 内に y という別の 2 つの変数が作成されることがすぐにわかりました。これはどのように可能であり、一体なぜJavaはそれを許可しているのでしょうか?

これはクラス Body の正しいコードだと思います。

public class Body extends Point{
    public double mass;

    public Body() {
        super();
        mass = 0;
    }

    public Body(double x, double y, double mass) {
        super(x,y);
        this.mass = mass;
    }
}

御時間ありがとうございます

4

4 に答える 4

17

ある意味では、スーパー クラスのフィールドをオーバーライドしています。しかし、フィールドのオーバーロードがないため、誤って実行する方がはるかに簡単です (指定された名前の変数は 1 つしかなく、型は関係ありません)。これは、変数の「隠蔽」または「シャドウイング」と呼ばれます。おっしゃる通り、同じ名前の 2 つのフィールドが作成されます。

2番目の例は正しいです。それらはスーパークラスから継承され、非公開と宣言されていないため、サブクラスから見えます。一般に、スーパークラスのフィールドを直接参照することはお勧めできません。正当な理由がない限り、それらはプライベートとして宣言する必要があります。スーパーコンストラクターを呼び出す例は、最良のアプローチです。

また、同じ名前の別のフィールドを非表示にした場合でも、それらを super.x、super.y、対 this.x、this.y として参照できます。可能な限り、この状況を避ける必要があります。

于 2009-04-21T13:49:16.470 に答える
7

はい、2 つの変数があり、一方が他方を隠しています。それを許可するのは、次の 2 つの理由から理にかなっています。

  1. 作成者がまったく知らない基本クラスBaseと派生クラスがあるとします。派生クラスフィールドを共有する可能性があるという理由だけで、の作成者はフィールドを追加できませんか? または、への変更が実際に正確さに影響しない場合、コンパイルを停止する必要がありますか?DerivedBaseBaseDerivedBase
  2. ほとんどの場合、フィールドはプライベートにする必要があります。その時点で、名前が重複しているかどうかは問題ではありません。どちらの「側」も、相手の変数を認識しません。
于 2009-04-21T13:52:11.393 に答える
4

他の人が言ったことにさらにBodyPointいいえ、Bodytype の位置プロパティがありPointます。したがってBody、おそらく拡張しないでくださいPoint。(実装の)継承を取り除けば、多くの問題が取り除かれます。それと使用private(ではありませんprotected!)とfinal自由に。

于 2009-04-21T13:57:59.133 に答える
1

これを行うと、Body クラス内に x という 2 つの変数が作成され、Body 内に y という別の 2 つの変数が作成されることがすぐにわかりました。これはどのように可能であり、一体なぜJavaはそれを許可しているのでしょうか?

実際にはいいえ、同じ名前の 2 つの変数を作成しているわけではありません。明らかに、コンパイラはこれを許可すべきではありません。

あなたxしているのは、 andとして定義された既存の変数をシャドーイングするyことです。つまり、Body.x と Body.y は基本的に Point.x と Point.y の名前と重なっており、後者の 2 つの変数は Body クラスから完全にアクセスできなくなります (へのリンク)。 「シャドウイング」の Java 言語仕様定義)。

名前のシャドーイングは一般的に悪い習慣であり、バグの原因であると認識されています。 javac コンパイラの警告を表示すると、コンパイラはこれについて忠実に警告します。

于 2009-04-21T13:51:58.540 に答える