Rubyのclass << selfとクラスメソッド、ならびに特異メソッドと特異クラス
Rubyライブラリのソースコードを読んでいると、よく class << self という構文が出てきます。
↓こんなの
class C class << self def foo puts 'foo' end end end C.foo #foo
最初見た時は?と思いましたが、ようはこれ(クラスメソッド定義)と同じでした。
class C def self.foo puts 'foo' end end C.foo #foo
肝は
・クラスメソッドとは、クラスの特異クラスのインスタンスメソッドである
・class << obj; endは、objの特異クラスを開く
という2点
なので、さきほどのコードに解説をつけるとこうなります
class C class << self # クラスCの特異クラスをオープン(このselfはクラスCなので) def foo # クラスCの特異クラスのインスタンスメソッド(=クラスCのクラスメソッド)を定義 puts 'foo' end end end C.foo #foo
さらに
・特異クラスのインスタンスメソッドのことを、特異メソッドと呼ぶ
・特異メソッドは、def obj.メソッド名; endで定義する
なので、以下は全て同義です
class C end # foo1 def C.foo1 puts "foo1" end # foo2 class << C def foo2 puts "foo2" end end # foo3 class C def self.foo3 puts "foo3" end end # foo4 class C class << self def foo4 puts "foo4" end end end # foo5 (class << C; self; end).send(:define_method, :foo5) {puts "foo5"} # foo6 # Ruby 1.9.2 以上 C.singleton_class.send(:define_method, :foo6) {puts "foo6"} C.foo1 #foo1 C.foo2 #foo2 C.foo3 #foo3 C.foo4 #foo4 C.foo5 #foo5 C.foo6 #foo6
class << self は、複数のクラスメソッドを定義する時に便利ですね
class C class << self attr_accessor :v def foo puts @v end end end C.v = 'foo' C.foo #foo