Rubyでクラスを作って色々処理を書いていると、セッターメソッド周りで意図しない挙動をしたりRubocop(静的コード解析ツール)に「冗長なself
つけんじゃねーよ」と怒られたりしたのでまとめます。
問題
問題のコードはこちらです、ギターをクラス化してみました。僕の趣味です。
class Guitar attr_accessor :color def initialize color = '赤' end def say_color "このギターは #{color} やで!" end end
では色を表示してみましょう。
guitar = Guitar.new
puts guitar.color
puts guitar.say_color
実行結果
このギターは やで!
うまく表示されません、つらい。
原因
原因はcolor = 'red'
のcolor
がローカル変数扱いされているからです。
Guitar#color=
が呼び出されているのではなく、新しく変数を作っています。で、使わずにソッコー捨ててます。
で、インスタンス変数の@color
はnil
のままです。
解決策
self
を付ければこのインスタンスのメソッドであることを明示できます。当てはめてみるとこんなコードになりますね。
class Guitar attr_accessor :color def initialize self.color = '赤' end def say_color "このギターは #{self.color} やで!" end end
では再度色を表示してみましょう。
guitar = Guitar.new
puts guitar.color
puts guitar.say_color
実行結果
赤 このギターは 赤 やで!
ちゃんと表示されましたね。うまくインスタンス変数に値が入っています。
冗長だと怒られる問題
ではRubocopに通してみたいと思います。
self.rb:9:15: C: Redundant self detected. "このギターは #{self.color} やで!"
「self
いらねーよ!」(意訳)と怒られてしまいました。ここはなくても大丈夫みたいですね。どこにいるのかいらないのかわからなくなってきました。
selfがいるところいらないところ
Rubyは変数の代入とセッターメソッドの違いをself
を使うことで区別するようです。
要はセッターメソッドの時にのみself
を付ければ良いわけですね。
def initialize #ここはRubyにとってはローカル変数かインスタンス変数かわからないのでローカル変数として扱う color = "赤" end
というわけでうまく動いて無駄なself
もないコードがこちらになります。
class Guitar attr_accessor :color def initialize self.color = '赤' end def say_color "このギターは #{color} やで!" end end
いい感じですね。しっかり使い分けることができました。
クラスを定義する上で扱う変数には気を配らないと訳がわからなくなるので、こういったところから気をつけようと思います。
- 作者: Peter J.Jones
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/19
- メディア: Kindle版
- この商品を含むブログ (5件) を見る