まりぴよこのブログ

日々の日記。技術ネタでまとまりきってないものの記録、伝わる文章の書き方を練習とか。

Rubyのミミックメソッド

ミミックメソッド

メタプログラミングRuby

メタプログラミングRuby

メタプログラミングRubyを読んでて、初めて出会った単語。。「ミミックメソッド」・・何だろ〜コレ?? ・・から、今までチラホラ見ていた self について新しい気付きがあったのでメモメモ!

付録Aのよく使うイディオム、1つ目の項目で出ていた「ミミックメソッド

Rubyでよく出てくる、属性へのgetter,setterを使う時なんかに、あたかも「メソッド呼び出しっぽくない」メソッド呼び出しのことを指しているらしい。

コード的にはこんな感じ

class Book
  def title
    @title
  end
  def title=(val)
    @title = val
  end
end

注:初心者(ワシか!)向け注意点。

普通はこんな風に書かない。 attr_accessor を使えば、Rubyがやってくれる。

ref.xaio.jp

とまあ。。普通にRubyコード書いてる分にはわざわざ書かないんだけど、Ruby的にgetter, setter はこんなふうにメソッドとして定義しているわけです。

こいつらを使う時、普通は

book = Book.new
# セッター使ってみる
book.title = 'メタプログラミングRuby'
# ゲッター使ってみる
book.title # => "メタプログラミングRuby"

なんだけど、実際のメソッド呼び出し的に厳密に書くと

book = Book.new
book.title=('メタプログラミングRuby')
book.title()

になる。 同じことなのでクリーンにかける最初の方式をみんな使ってる。

こんな感じで、他言語(Javaとか)出身者からすると、「あ〜publicなtitle属性定義して、直アクセスしてるわけね〜」と思ってしまうのだが、実際はメソッド経由なわけだ。

「他の何かに擬態している」メソッドなので、ミミックメソッド、と呼ぶらしい。

なるほどなるほど。。 ここまではなんとなく他のRubyの本とかで文法勉強してた時に聞いたことある感。

属性の不具合

ここで注意!

class MyClass
  attr_accessor :my_attr

  def initialize_attributes
    my_attr = 10
  end
end

こう書いてしまうと予期せぬバグを生み出してしまう・・そうだ・・

最初全くピンとこず・・

実行すると、こんなんなっちゃう。。

obj = MyClass.new
obj.initialize_attributes
obj.my_attr # => nil

10どこ行ってん!!!(涙)

理由

原因は initialize_attributes でのコードが曖昧なこと。

Ruby的にはこのコードが

  1. ローカル変数 my_attr に代入
  2. ミミックメソッド my_attr=() の呼び出し

なのか、区別がつかない。

迷ったらRubyは1を採用するそうだ。(確かにそっちのほうが明確。2はより厳密な指定方法があるわけだし)

回避策

class MyClass
  attr_accessor :my_attr

  def initialize_attributes
    self.my_attr = 10
  end
end

ここでselfが登場!!

こうすると曖昧さがなくなり、ミミックメソッドの呼び出し!ということがRubyに伝わる。

なので、「カレントオブジェクトの属性に代入する時は、明示的に self を使うこと」が重要なのだ。

雑感

今までなんとなく、 カレントオブジェクトの属性に代入には必ず self 付いてるの、Ruby的なお約束かな〜とかぼんやりと思ってたけど、(まあ確かにお約束といえばお約束だが)裏にある意味をちゃんと理解するって大事!

いや〜なんかスッキリした!