質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

1回答

1162閲覧

Rubyのインスタンス変数とローカル変数の挙動でわからないことがあります。

tukimi05

総合スコア7

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

2クリップ

投稿2018/03/03 03:30

前提・実現したいこと

プロを目指す人のためのRuby入門という書籍を読み進めている中で、ローカル変数とインスタンス変数の挙動について理解できない箇所があり、
アクセスメソッドをいじってみたり実験をしてみたのですが、なぜこんな挙動をするのか理解ができなかったので、教えていただけると助かります。

発生している問題・エラーメッセージ

ruby

1class Product 2 attr_reader :name, :price 3 4 def initialize(name, price) 5 @name = name 6 @price = price 7 end 8 9 def to_s 10 # ここでなぜローカル変数を呼んでいるのか? 11 "name: #{name}, price: #{price}" 12 end 13end 14 15class DVD < Product 16 attr_reader :running_time 17 18 def initialize(name, price, running_time) 19 super(name, price) 20 @running_time = running_time 21 end 22end 23 24product = Product.new('A greate movie', 1000) 25p product.to_s #=> "name: A great movie, price: 1000"

コンストラクタではローカル変数をインスタンス変数にセットしているため、
コンストラクタで引数として定義されているname, priceのスコープはコンストラクタの中でのみ有効だと思っていました。
ですが、to_sメソッドではインスタンス変数を呼ぶような形でname、priceの値を呼び出すことに成功しています。(上記コードのコメントを書いている箇所です)

試したこと

私は下記の様な形でto_sメソッドではインスタンス変数を使わなければnameとpriceの値は呼び出せないと思っていました。(ローカル変数をto_sメソッドで呼ぶとエラーとなることを期待していた)

ruby

1def to_s 2 "name: #{@name}, price: #{@price}" 3end

試しにインスタンス変数で値の呼び出を行ったところ、こちらでも呼び出すことはできました。
その後、試しにアクセスメソッドを削除してみたところ、もともと期待していたエラーが返ってくるようになりました。

`to_s': undefined local variable or method `name' for #<Product:0x007fb22298a810 @name="A great movie", @price=1000> (NameError) Did you mean? @name

アクセスメソッドはインスタンス変数の「参照」「変更」を可能にするため存在するのだと思っていたのですが、ローカル変数の挙動まで変わってしまうのでしょうか?
そもそも、to_sの中で読んでいたname,priceがローカル変数ではなかったりするのでしょうか?
Rubyに関して知識が浅いので認識を間違えている箇所等あればご指摘いただけるとうれしいです。
よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-darwin17]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ですが、to_sメソッドではインスタンス変数を呼ぶような形でname、priceの値を呼び出すことに成功しています。(上記コードのコメントを書いている箇所です)

いえ、これはローカル変数ではなくアクセサメソッドを呼んでいます。

nameのようなトークンが出現した場合、すでにローカルで変数が宣言されていなければ、それはメソッドとして解釈されます。

投稿2018/03/03 03:58

編集2018/03/03 04:00
maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tukimi05

2018/03/03 05:35 編集

> いえ、これはローカル変数ではなくアクセサメソッドを呼んでいます。 なるほどattr_readerは ``` def name @name end ``` が定義されたのと同義であるため、nameはメソッドを読んだ扱いとなったのですね。 nameと見たときに先入観からローカルメソッドであると思いこんでいました。 ありがとうございました。やっと理解することができました。
jnchito

2018/03/03 21:09 編集

こんにちは。執筆者の伊藤です。 少し捕捉させてもらうと、Rubyはその文法上、メソッドの呼び出しとローカル変数の参照の見分けが付きづらい(書き方によってはまったく同じになる)ので、このような疑問が出てくるのはもっともです。 ご質問の内容は書籍内の7.5節~7.5.1項でも説明しているので、こちらをもう一度読み直してもらうと、さらに理解が進むかもしれません。 以上、ご参考までに。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問