Rubyにattr_accessor
ってメソッドありますよね。こんなのです。
class Book attr_accessor :title, :price def initialize(title, price) @title = title; @price = price end end
「getter」と「setter」を定義してくれるメソッドですが、Rubyからプログラミングを始める初心者殺しだと思ってます。
「getter」と「setter」が何者なのか理解しきれなかった当初は苦しみました。
特にsetterメソッド。
def hogehoge=(val)
ってなんぞや・・・
ということで今回は実際に自分が詰まった箇所「attr_accessor」の説明と
def title=(val) end
という「setterメソッド」定義の最初の躓きポイントをプログラミング初心者に向けて分かりやすく書いていきます。
def title=(val) ってなんだ
以下のコードにて
「Bookインスタンス」が「インスタンス変数title」を呼び出したり
「インスタンス変数price」に値を代入したり出来ているのは
「attr_accessor」
のおかげです。
ここまでは初心者でも「そういうものなんだ」と理解出来ます。
class Book attr_accessor :title, :price def initialize(title, price) @title = title; @price = price end end book = Book.new("Programming Ruby", 1980) puts book.title book.price = 2000 puts book.price
では、「attr_accessorを使わない場合」の記述を見てみます。
class Book def initialize(title, price) @title = title; @price = price end def title @title end def title=(val) @title = val end def price @price end def price=(val) @price = val end end
「attr_accessor」を記述しない代わりに、「4つ」インスタンスメソッドが増えました。
単に1つのインスタンス変数にアクセスする代わりに
「読み込み用」と「書き込み用」
のメソッドを用意しただけです。
しかし、初めの頃ある一行にとても違和感を感じました。
def title=(val)
これです。
def title=(val) の正体
「メソッド定義ってこうやるんだよね?」
def title
「そうそう、def の後に打ち込んだ文字のメソッドが定義される」
じゃあこれは?
def title=(val)
「うわ、文字のあとに変な =(val) が付いている・・・」
これだけで大パニック。今までのメソッド定義の固定観念が覆される衝撃です。
しばらくこのコードの意味不明さには悩みました。
「titleだけのメソッドがあるからこっちが「setter」ってやつに違いないはず・・・」
「そもそもvalってなんだよ・・・」
正解
def title=(val) とは
book.title = "test"
と「title」への代入式を書いた時に呼び出されるメソッド。
決して「title=(val)」という命名のメソッドではない。
分からなかった理由
- 「メソッド名」と 「=」 と 「引数」がくっついてたから
- valが何かの魔法のコトバだと思い込んでたから
代入と言ったら title = val のようなスペースを空けた形だけだと考えてました。
また、val
も単なるvalue
の略で「引数」を表していただけ。
str
やらval
やら変数の略称ってたくさんあります。
ただ、プログラミング初心者にはそれが躓く原因となったりします。
省略した書き方を知らないと、意外な所で理解の妨げになる恐れがありそうです。
コメント
誤解を招きそうな表現ですが、それは「title=」という命名のメソッドです。Rubyのメソッド名に記号が含まれることは、ちょいちょいあります。
上のBookクラスのインスタンスbにたいして、「b.title=(“広辞苑”)」と書くのと「b.title = “広辞苑”」と書くのは全く同じです・・・というか、後者の書き方は前者を簡単に書くための記法に過ぎません。同様に、「b.title + “新明解”」は「b.title().+(“新明解”)」という意味になります。つまり、+も演算子ではなく、名前に記号を含んだ(というか記号1文字だけの)メソッドです。
この様にRubyでは人間が書きやすいようにもの凄く頑張っているため、Rubyコードを解釈するプログラムは超複雑になって困っているらしいですが、「Rubyを作る人より使う人の方が多いのだから、作る人が苦労すべきだ」というのがRubyを作っている人達のポリシーなのです。
コメントありがとうございます。
使う人が書きやすい「title = val」のみが代入形式だと考えていると、
「title=(val)」の「=(val)」がメソッド呼び出しだと気付かず、普通のメソッド定義と勘違いしてしまうのでは、という意図で書いていました。
代入と言って最初に思い浮かべるのは、
「title = val」のような「=」の前後にスペースを含む書き方。
しかし、Rubyではこちらがシンタックスシュガーであり、上記は「title=」というメソッドを呼び出しているだけ、ということですよね。
http://i.loveruby.net/ja/rhg/book/spec.html