Java の別のクラスを拡張するクラス内に同じ名前の 2 つの変数がある
質問
以下はプロジェクトのコードの一部です。
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 と呼ばれ、Body 内の他の 2 つの変数は y と呼ばれます。これはどのようにして可能でしょうか?また、一体なぜ 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;
}
}
御時間ありがとうございます
解決
ある意味では、あなたは、スーパークラスのフィールドをオーバーライドしています。しかし、それはフィールドのないオーバーロードがないため、誤って行うことがはるかに簡単だ(あなたが唯一の指定された名前の一つの変数を持って、種類は関係ありません)。これは、変数「隠し」または「シャドーイング」と呼ばれます。だから、あなたが正しいなら、あなたは同じ名前を持つ2つのフィールドになってしまいます。
あなたの第二の例は正しいです。彼らは、スーパークラスから継承され、それらがプライベートで宣言されていないので、彼らはサブクラスに表示されます。これは、スーパークラスのフィールドを直接参照するには、一般的に悪い習慣だし、正当な理由がない限り、彼らはプライベート宣言しなければなりません。スーパーコンストラクタを呼び出すあなたの例では、最善のアプローチです。
同じ名前の別のフィールドを非表示にした場合では、すべての場合は、また、あなたはまだsuper.x、super.y、対this.x、this.yとしてそれらを参照することができ、あなたはこのような状況を避ける必要があります可能。
他のヒント
はい、変数が 2 つあり、一方がもう一方を隠しています。次の 2 つの理由から、これを許可するのが理にかなっています。
- 基本クラスがあるとします。
Base
そして派生クラスDerived
その作者がBase
については何も知りません。の著者は、Base
派生クラスであるため、フィールドを追加することはできません かもしれない 畑を共有しますか?あるいはすべきだDerived
に変更されたときにコンパイルを停止しますBase
実際には正しさに影響しないのでしょうか? - フィールドはほとんどの場合プライベートである必要があり、その時点では名前が重複しているかどうかは問題ではありません。どちらの「側」も相手の変数について知りません。
また、他の人が言ったことへ:Body
はPoint
ですか?いいえ、Body
はタイプPoint
の位置プロパティがあります。だから、Body
はおそらくPoint
を拡張するべきではありません。あなたが相続を取り除く場合(実装の)あなたは多くの問題を取り除きます。それと自由に使用private
(protected
ない!)とfinal
ます。
これを実行すると、Body クラス内に x という 2 つの変数が作成され、Body 内に y という別の 2 つの変数が作成されることにすぐに気づきました。これはどのようにして可能でしょうか?また、一体なぜ Java ではそれが許可されているのでしょうか?
実際には、同じ名前の 2 つの変数を作成しているわけではありません。明らかにコンパイラはこれを許可すべきではありませんし、許可しません。
あなたは何ですか は 次のように定義されている既存の変数をシャドウイングしています。 x
そして y
, つまり、Body.x と Body.y は基本的に Point.x と Point.y の名前と重複しており、後者の 2 つの変数には Body クラスから完全にアクセスできなくなります (「シャドウイング」の Java 言語仕様定義へのリンク).
名前のシャドウイングは一般に悪い習慣であり、バグの原因であると認識されており、javac コンパイラの警告をオンにすると、コンパイラは律儀にこれについて警告します。