question2024
@question2024 (step1engineer)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

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

0

3Answer

「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);

1Like

getFoo1()の処理は{return f}で
どうしてここにgetX()を.で繋げられるのかが
理解できていません。

fFoo1クラスのインスタンスを持つ変数です。ですから、Foo1クラスのインスタンスメソッドを普通に呼べます。次のコードと等価です。

//  f2.getFoo1().setX(100);
    Foo1 f = f2.getFoo1();
    f.setX(100);
1Like

Comments

  1. @question2024

    Questioner

    ご回答いただきましてありがとうございます。
    いただいたコメントをみて、確かに、、、となりました。
    ちなみにjavaは独学で、業務での使用経験もなく、
    ちんぷんかんぷんな質問かもしれませんが、
    もし可能なら教えていただきたいです。

    class Foo2のなかに
    Foo1クラスのインスタンスを持つ変数を作る
    というコードについてですが、
    このように
    あるクラスのなかに
    違うクラスのインスタンスを持つ変数を用意するようなケースは
    どのようなプログラムを書くときに便利なのでしょうか。
    8行目の Foo1 f; についても Foo1の型ならなぜ Foo1クラスの方で
    fを作らないのでしょうか。
    質問の内容が意味が分からない、、等ありましたら
    スルーしていただいて結構ですm(_ _)

  2. 8行目の Foo1 f; についても Foo1の型ならなぜ Foo1クラスの方で
    fを作らないのでしょうか。

    「自分のクラスのメンバーとして自分のインスタンスを持つ」って、どういう意味になりますか?

    ListとかTreeのようなデータ構造であれば、そういった持ち方をすることがありますが、
    それ以外の場面では、思いつかないです・・・


    あるクラスのなかに
    違うクラスのインスタンスを持つ変数を用意するようなケースは
    どのようなプログラムを書くときに便利なのでしょうか。

    便利というか、複数種類のクラスが存在し合うプログラムであれば、必然的に「あるクラスのインスタンスが、別なクラスのインスタンスを保持する」の構造になります。

    オブジェクト指向設計を勉強すると、具体的に理解が進むと思います。

念のため確認なのですが、元のは「コンパイルエラーが起こらない(文法的に正しい)選択肢を複数回答せよ」みたいな設問で
質問文に挙げられている2つが正解だった、という認識でよいでしょうか?
そして質問としては「文法的に f2.getFoo1().setX(100); が正しい理由を知りたい」でよいでしょうか?

(「実行時例外が発生するのはどの選択肢か」とかだとちょっとだけ話が変わるかもなので…)

文法的な疑問だとして、質問への回答

  1. f1.setX(100);
  2. f2.getFoo1().setX(100);

説明1.

変数f1Foo1型の値です。
ですのでf1直後にドットで繋げる記法でFoo1型の許可された非staticなフィールド変数やメソッドにアクセスできます。

説明2.

f2.getFoo1()つまりFoo2クラス宣言内の、getFoo1()メソッド宣言の戻り値はFoo1型であり、呼び出した結果はFoo1型の値になります。
ですのでgetFoo1()直後にドットで繋げる記法でFoo1型の許可された非staticなフィールド変数やメソッドにアクセスできます。

(このようにメソッドの戻り値にさらにメソッドを繋げる書き方を、メソッドチェーンと呼びます)

合わせて

上記の説明1と説明2は、実はほぼ同じことが書いてあります。
つまりどういう記述であろうがFoo1型の値になるならば、それ以降は同じようにFoo1に対する記述が可能です。


ちなみに、ここで

getFoo1()の処理は{return f}で

処理の中身は気にしてはいけません
メソッドチェーンの際に気にすべきは、メソッドの戻り値ののみです。

戻り値がFoo1型の値なので、Foo1型の処理を続けて書ける、というだけです。

1Like

Comments

  1. @question2024

    Questioner

    ご回答いただきましてありがとうございます。
    ご指摘をいただき気が付きました。
    問題の文章をきちんと書けていませんでした。
    今回の問題文では、100と表示させたい場合どの選択肢が正解ですか
    と問うものでした。
    今後質問をするときには、問いと正解以外の選択肢も載せるよう気を付けます!
    ありがとうございます。

    いただいた文章をこれからじっくり読ませていただきます!!
    ちなみに以降にその他アドバイスも頂けてとても嬉しいです。
    ありがとうございます。!!

Your answer might help someone💌