人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

class A {
int x = 10;
void hello () {
System.out.println("Hello A with " + x);
}
}
class B extends A {
int x = 20;
void hello () {
System.out.println("Hello B with " + x);
}
}
class Test {
public static void main (String args[]) {
A obj = new B();
obj.hello();
System.out.println("x = " + obj.x);
}
}
このプログラムを実行すると、
Hello B with 20
x = 10
となりますが、
Hello B with 20 は理解できます。
x = 10 となる理屈がわかりません。
このオブジェクト思考の理屈が理解できるURLはありませんか。

●質問者: patacyan
●カテゴリ:コンピュータ インターネット
✍キーワード:Class Hello Out String test
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● koriki-kozou
●30ポイント

int x = 10;はスーパークラスのメンバ変数

どこからでも参照可能


int x = 20;はサブクラスのメンバ変数

定義したサブクラス以下でのみ参照可能

上位のメンバ変数にオーバーラップ可能


System.out.println("Hello B with " + x);からは同じクラス内でオーバーラップされた20のほうを参照

クラス外からはラップされたものは見えないでスーパークラスのメンバ変数だけが見える


http://www.atmarkit.co.jp/fjava/rensai2/javaent04/javaent04.html

◎質問者からの返答

ありがとうございます。

もっと勉強させてもらいます。


2 ● hnagoya
●30ポイント

「オブジェクト思考の理屈」ではなく Java の仕様・実装がそうなっているだけのようですが、以下のURLがご質問に該当する内容のように思います。

Javaの“常識”、“非常識” - 第2回 言語仕様編

Q.05 サブクラスでスーパークラスのインスタンス・フィールドをオーバーライドしているのに、期待したとおりの結果が得られません……

A.05 サブクラスでオーバーライドできるのはメソッドのみで、スーパークラスのインスタンス・フィールドを「オーバーライド」することはできません

http://www.itarchitect.jp/technology_and_programming/-/27052-5.h...

◎質問者からの返答

> Java の仕様・実装がそうなっているだけ

> スーパークラスのインスタンス・フィールドを「オーバーライド」することはできません

なるほど、そうだったんですね。

ありがとうございます。


3 ● quintia
●40ポイント ベストアンサー

"オーバーライドすることはできない"は、"エラーにする"のではなくて、"隠蔽してしまう"の意です。

サブクラスの中で、スーパークラスと同じ名前のフィールドを宣言すると、スーパークラスのフィールドは隠蔽されます。


質問のソースは、

class A {
 int x = 10;
 void hello () {
 System.out.println("Hello A with " + x);
 }
}

class B extends A {
 int x2 = 20; //衝突しない名前にする
 void hello () {
 System.out.println("Hello B with " + x2);
 }
}

class Test {
 public static void main (String args[]) {
 A obj = new B();
 obj.hello();
 System.out.println("x = " + obj.x);
 }
}

と書いたのと同じです。

こう書けば質問のソースでは、

が理解できるかと思います。


この仕様の意図は、スーパークラスの修正のしやすさからのものです。

class A {}

class B extends A {
 int x = 10;
 void hello () {
 System.out.println("Hello B with " + x);
 }
}

とあるとします。hello()メソッド中のxがBのフィールドを指すのは自明です。

このあと、

class A {
 float x = 0.0f;
 void hoge() {
 x = ...;
 }
}

class B extends A {
 int x = 10;
 void hello () {
 System.out.println("Hello B with " + x);
 }
}

と修正した時に、B中に書いたxがAのフィールドを(オーパーライドして)指してしまっては大変です。

ましてやこれらが、同じソースファイルでない、そもそもソースファイルがない、という状況だと面倒なことになります。


サブクラスでスーパークラスと同じ名前のフィールドを宣言する、あるいはメソッド内でクラスフィールドと同じ名前の変数を宣言する、などした時に後者が隠蔽される理由が分かるのではないでしょうか。


http://java.sun.com/docs/books/jls/second_edition/html/classes.d...

◎質問者からの返答

今すぐには理解できないんですが、今後しっかり勉強させてもらいます。

みなさん、ありがとうございました。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ