「f2.setFoo1(f1);」が実行されたら、f2の内部変数fはf1そのものです。また、f2.getFoo1()の戻り値はfです。
つまり、f2.f==f1 && f2.getFoo1()==f2.f です。つまり、f2.getFoo1()==f1 です。
そして、以下2行は同等です。
f1.setX(100);
f2.getFoo1().setX(100);
java silver 紫本 第5章について質問
java silver se11 紫本
ページ205~206の問題についての質問です。
class Foo1 {
int x;
void setX(int x){this.x = x;}
int getX(){return x;}
}
class Foo2{
Foo1 f;
void setFoo1( Foo1 f){ this.f = f;}
Foo1 getFoo1(){return f;}
}
public class Main{
public static void main(String[] args){
Foo1 f1 = new Foo1();
Foo2 f2 = new Foo2();
int a = 10;
f1.setX(a);
f2.setFoo1(f1);
// ここにはいるコード
System.out.print(f2.getFoo1().getX());
}
}
// ここに入るコード
にはどのコードが入りますが?という選択肢の問題で、
答えは以下の2つです。
f1.setX(100);
f2.getFoo1().setX(100);
解説を読んで、
f1.setX(100);
↑この選択肢がOKなことは理解できた
f2.getFoo1().setX(100);
↑こちらのコードが理解できない
という状況です。
f2.getFoo1().setX(100); は、
「変数f2が参照しているオブジェクトであるgetFoo1を呼び出して、
その結果をsetX(100)で処理する。」
ということを意味するコードだと理解しているのですが、
getFoo1()の処理は{return f}で
どうしてここにgetX()を.で繋げられるのかが
理解できていません。
この部分に関しての理解のポイントでも、
もしくはそこが分からないならまずここが理解できている?などの
ご指摘でも嬉しいです。
理解するためのアドバイスをいただけたら嬉しいです。
よろしくお願いいたします。m(_ _)m
3Answer
getFoo1()の処理は{return f}で
どうしてここにgetX()を.で繋げられるのかが
理解できていません。
f
はFoo1
クラスのインスタンスを持つ変数です。ですから、Foo1
クラスのインスタンスメソッドを普通に呼べます。次のコードと等価です。
// f2.getFoo1().setX(100);
Foo1 f = f2.getFoo1();
f.setX(100);
Comments
@question2024
Questionerご回答いただきましてありがとうございます。
いただいたコメントをみて、確かに、、、となりました。
ちなみにjavaは独学で、業務での使用経験もなく、
ちんぷんかんぷんな質問かもしれませんが、
もし可能なら教えていただきたいです。class Foo2のなかに
Foo1クラスのインスタンスを持つ変数を作る
というコードについてですが、
このように
あるクラスのなかに
違うクラスのインスタンスを持つ変数を用意するようなケースは
どのようなプログラムを書くときに便利なのでしょうか。
8行目の Foo1 f; についても Foo1の型ならなぜ Foo1クラスの方で
fを作らないのでしょうか。
質問の内容が意味が分からない、、等ありましたら
スルーしていただいて結構ですm(_ _)8行目の Foo1 f; についても Foo1の型ならなぜ Foo1クラスの方で
fを作らないのでしょうか。「自分のクラスのメンバーとして自分のインスタンスを持つ」って、どういう意味になりますか?
ListとかTreeのようなデータ構造であれば、そういった持ち方をすることがありますが、
それ以外の場面では、思いつかないです・・・
あるクラスのなかに
違うクラスのインスタンスを持つ変数を用意するようなケースは
どのようなプログラムを書くときに便利なのでしょうか。便利というか、複数種類のクラスが存在し合うプログラムであれば、必然的に「あるクラスのインスタンスが、別なクラスのインスタンスを保持する」の構造になります。
オブジェクト指向設計を勉強すると、具体的に理解が進むと思います。
念のため確認なのですが、元のは「コンパイルエラーが起こらない(文法的に正しい)選択肢を複数回答せよ」みたいな設問で
質問文に挙げられている2つが正解だった、という認識でよいでしょうか?
そして質問としては「文法的に f2.getFoo1().setX(100);
が正しい理由を知りたい」でよいでしょうか?
(「実行時例外が発生するのはどの選択肢か」とかだとちょっとだけ話が変わるかもなので…)
文法的な疑問だとして、質問への回答
f1.setX(100);
f2.getFoo1().setX(100);
説明1.
変数f1
はFoo1型
の値です。
ですのでf1
直後にドットで繋げる記法でFoo1型
の許可された非staticなフィールド変数やメソッドにアクセスできます。
説明2.
f2.getFoo1()
つまりFoo2
クラス宣言内の、getFoo1()
メソッド宣言の戻り値はFoo1型
であり、呼び出した結果はFoo1型
の値になります。
ですのでgetFoo1()
直後にドットで繋げる記法でFoo1型
の許可された非staticなフィールド変数やメソッドにアクセスできます。
(このようにメソッドの戻り値にさらにメソッドを繋げる書き方を、メソッドチェーンと呼びます)
合わせて
上記の説明1と説明2は、実はほぼ同じことが書いてあります。
つまりどういう記述であろうがFoo1型
の値になるならば、それ以降は同じようにFoo1
に対する記述が可能です。
ちなみに、ここで
getFoo1()の処理は{return f}で
処理の中身は気にしてはいけません。
メソッドチェーンの際に気にすべきは、メソッドの戻り値の型のみです。
戻り値がFoo1型の値なので、Foo1型の処理を続けて書ける、というだけです。
Comments
@question2024
Questionerご回答いただきましてありがとうございます。
ご指摘をいただき気が付きました。
問題の文章をきちんと書けていませんでした。
今回の問題文では、100と表示させたい場合どの選択肢が正解ですか
と問うものでした。
今後質問をするときには、問いと正解以外の選択肢も載せるよう気を付けます!
ありがとうございます。いただいた文章をこれからじっくり読ませていただきます!!
ちなみに以降にその他アドバイスも頂けてとても嬉しいです。
ありがとうございます。!!