Rubyのattr_accessor
,attr_reader
, attr_writer
等が良く分からなくて,モヤモヤしていたので,調べて自分なりに納得したことをまとめておく.
例として以下のコードを考える.
class Triangle
attr_accessor :baseLength, :height
def initialize(baseLength, height)
@baseLength = baseLength
@height = height
end
end
sankaku = Triangle.new(10.0, 3.0)
puts sankaku.baseLength
puts sankaku.height
クラスの定義の中で
attr_accessor :baseLength
のように書くとクラスのインスタンス変数@baseLength
に
sankaku.baseLength
のようにアクセス可能になる.ここで個人的に気持ち悪かったのは,インスタンス変数名は@
で始まるから
sankaku.@baseLength
とアクセスするようにしてもよさそうなのにそうなっていないこと.あと,
attr_accessor :baseLength
がインスタンス変数を外からアクセス可能にするための記述だというのなら,なぜ
attr_accessor @baseLength
のように記述しないのだろう?
まぁそれがRubyの仕様だと言ってしまえばそれまでだけど,,,,
いろいろ調べて,「まつもと直伝 プログラミングのオキテ 第6回」が一番腑に落ちた.これによると,
attr_accessor
は内部的に次のような処理を行っています。(1)引数のシンボルすべてに対して以下の処理を繰り返す。
(2)シンボルで指定された名前のメソッドを定義する。そのメソッドはシンボルの名前の先頭に「
@
」を付加したインスタンス変数の値を取り出す。(3)シンボルで指定されたメソッド名の後ろに「
=
」を付加した名前のメソッドを定義する。そのメソッドは引数を1つ取り,その値をシンボルの名前の先頭に「@
」を付加したインスタンス変数に設定する。
とある.これから分かるのは,まず
sankaku.baseLength
のbaseLength
はインスタンス変数ではなくインスタンス変数@baseLength
の値を返してくれるメソッドだということです.これで最初の私のモヤモヤ感は解消しました.
また2番目の気持ち悪さも,
attr_accessor :baseLength
という記述は,インスタンス変数を外からアクセス可能にする,ということをやっているのではないということですから,解消されます.つまりこの baseLength
はインスタンス変数 @baseLength
を意味しているのではなく,メソッドの名前なのだから @
が付かなくて当然です.