LoginSignup
1
1

More than 5 years have passed since last update.

Q: singleton_method_added() って何? A: 「フック」

Last updated at Posted at 2016-03-16

きっかけ

を見かけて、いったい何がおかしいのか、そもそも`singleton_method`ってなんだ?と思ったところが始まり。  クラスの理解もおぼつかない初心者が @shyouhei を質問攻めにしながらその謎に迫ります。

singleton_methodとは?

 日本語で言うところの特異メソッド。普通のメソッドはクラス定義に書かれており、そのクラスから作ったインスタンスで利用できるものだけれど、特異メソッドはとある一つのインスタンスにだけ追加されるメソッドのこと。

singleton_method_test1.rb
str1 = String.new
def str1.new_singleton_method
  puts "str1の特異メソッドだよ"
end
str1.new_singleton_method
# => str1の特異メソッドだよ

str2 = String.new
str2.new_singleton_method
# => undefined method `new_singleton_method' for "":String (NoMethodError)

 しかし、ruby-doc ( http://docs.ruby-lang.org/ja/2.2.0/doc/spec=2fdef.html#singleton_method ) を見てみるとクラスの特異メソッドと書いてある。しかも継承されると。クラスの特異メソッドってなんだ!?インスタンス化されたものにだけ追加できるメソッドじゃないのか!?と思ったら、私のクラスに対する理解が浅いだけでした。クラスはClassというクラスのインスタンス。 ( http://docs.ruby-lang.org/ja/2.2.0/doc/spec=2fdef.html#class ) にそう書いてある。だからクラスにも特異メソッドを追加できる。でもそれはクラスメソッドと同じように見える。というかクラスメソッドをクラスの特異メソッドとして実装している?書き方としてはこんな感じ。

singleton_method_test2.rb
class Foo
  def Foo.new_singleton_method
    puts "Fooの特異メソッドだよ"
  end
end

Foo.new_singleton_method
# => Fooの特異メソッドだよ

 見た目クラスメソッドと差がないですね。ちなみにこれが継承される、という話はちょっと変。とある一つのインスタンスにのみ追加されるメソッドが特異メソッドのはずなので。でもここは「変だけど使い勝手優先」by @shyouhei らしいです。

では、 singleton_method_added() って何?

 これは

singleton_method_added_sample1.rb
class Foo
  def singleton_method_added(n)
    puts "新しく追加された特異メソッドは以下だよ"
    p n
  end
end

foo = Foo.new
def foo.new_singleton_method1
end
# => 新しく追加された特異メソッドは以下だよ
# => :new_singleton_method1

こんな風に使える。
 この singleton_method_added() の中身が、新たに特異メソッドが追加された時に実行されるのだ。引数として渡せるのは新たに追加された特異メソッド名のシンボル ( http://docs.ruby-lang.org/ja/2.2.0/class/Symbol.html ) 。

 その振る舞い方はわかった。けれども、このsingleton_method_added()ってなんて呼べばいいんだろう?名前があらかじめ決まっている、という意味ではビルトインメソッドのように思えるけど、呼び出されるタイミングは決まってる上その振る舞いは定義されていないので、ビルトインメソッドとはまた違う。メソッドであることは確かだけど、その名前を自由に決められないし、どのタイミングで動くのかということもあらかじめ決まっているから、単純にメソッドと呼ぶのにも抵抗がある。
 なので、なんて呼べばいいか @shyouhei に聞いてみたところ、「フック」との答えが。なるほど。特定のタイミングで割り込むからフックなのか。となんだか納得。

そして、冒頭のバグ?の意味

 冒頭のバグ#12131は、singleton_method_added()そのものをインスタンス化したオブジェクトの特異メソッドとして追加した時に、singleton_method_added()自体が動いてしまうのはおかしくないか?という問いだったのだ。
 そして、それはおかしくないよね、いやおかしい、という感じでTwitterで議論がされている、と。
 この議論についてはベテランの皆様に任せるのが一番いいと思うので、私の探求はここで終わり。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1