Rubyのsetterメソッドを呼ぶ時はレシーバをつける
『Effective Ruby』を読むメモ。前回の日記はこちら。
コードを書いていたら、さっそくこの本の内容が役立ちました。eqlとhashを上書きする話です。
3章の途中まで読んだ後、後ろの方の気になるところをチラ見しています。今日の復習は、2章の項目9です。
- 作者: Peter J. Jones,arton,長尾高弘
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/09
- メディア: 大型本
- この商品を含むブログ (13件) を見る
項目9 Rubyの最悪に紛らわしい構文に注意しよう
まずは「Rubyプログラマが比較的よくしたがっている緩やかなガイドライン」の紹介がある。
- メソッド名の末尾に?をつける: 真偽値を返す
- メソッド名の末尾に!をつける: レシーバを書き換えることを示す。あるいは有害な副作用の警告
- メソッド名の末尾に=をつける: setterになる
なるほど。項目9では、主にsetterの話をしている。
setterを使う時にはレシーバを指定しなければならない、というのが今回のポイントだった。また、setter以外の場所で不要なレシーバselfをたくさん書いて、コードをごちゃごちゃさせるのはやめようとも、筆者は主張している。
サンプルコード
次のようなname_bad.rbがあるとする。ちなみに、attr_writerとattr_accessorは、setterを書いてくれるヘルパーメソッド。
class Name attr_accessor(:first, :last) def initialize(first, last) first = first last = last end def full first + " " + last end end man0 = Name.new("Taro", "Yamada") puts man0.full
initializeの中でsetterを呼んでいる。と思いきや、呼べていない。
レシーバがないので、first、lastというinitializeメソッド内のローカル変数に、引数の値を代入することになる。レシーバという言い方、なんかトラディショナルですね。
上のコードを実行すると、fullメソッドを呼び出した時に、firstとlastがnilでエラーになる。
% ruby name_bad.rb name_bad.rb:10:in `full': undefined method `+' for nil:NilClass (NoMethodError) from name_bad.rb:15:in `<main>'
次のようにレシーバselfを指定すると、正しく「Taro Yamada」と出力される。
def initialize(first, last) self.first = first self.last = last end