読んだだけじゃ絶対にわすれるので、メモっとく。
特異メソッド
クラスに属するすべてのオブジェクトではなく、単一のオブジェクトだけのために定義されたメソッド
オブジェクトの特異メソッドは、そのオブジェクトのクラスによって定義されない。
そのオブジェクトに対応付けられた無名の特異クラスのインスタンスメソッドである。
無名の特異クラスのことをシングルトンクラス、メタクラスと呼ぶ。
各インスタンスごとに特異クラスを持つ。
classのインスタンスClass1の特異メソッドは、Class1クラスのクラスメソッドであり、
classのインスタンスであるClass1の特異クラスのインスタンスメソッドである。
試してみた。
- # ClassクラスのインスタンスであるPointオブジェクトに特異メソッドを定義
- # Pointクラスのクラスメソッドになる
- class Point; end
- def Point.sum x, y; x + y; end
- p Point.sum 1,2 #=> 3
- # 特異メソッドを複数定義時に便利な構文糖
- class << Point
- def minus x, y; x - y; end
- def multi x, y; x * y; end
- end
- p Point.minus 1,2 #=> -1
- p Point.multi 1,2 #=> 2
- # クラス定義中にクラスメソッドを複数定義するときに便利な構文糖
- # class << self は特異クラス(classのインスタンスであるPointクラスオブジェクト)
- class Point
- class << self
- def div x, y; x / y; end
- end
- def self.eignclass
- class << self; self; end
- end
- end
- # p1オブジェクトの特異メソッドを定義
- p1 = Point.new
- def p1.sum x, y, z; x + y + z; end
- p p1.sum(1, 2, 3) #=> 6
- # p2からはp1の特異メソッドは見えない
- p2 = Point.new
- #p p2.sum(1, 2, 3) #=> NoMethodError
- class << p2
- def sum x, y ,z, a; x + y + z + a; end
- def multi x, y ,z, a; x * y * z * a; end
- end
- p p2.sum 1, 2, 3, 4 #=> 10
- p p2.multi 1, 2, 3, 4 #=> 24
- # p2からはP1特異メソッド特異メソッドは見えない
- #p p1.sum 1, 2, 3, 4 #=> NoMethodError
- # 実行結果
- # 3
- # -1
- # 2
- # 6
- # 10
- # 24
もう一丁。
- class Class1
- puts "#{self.__id__} before open singleton class"
- class << self
- puts "#{self.__id__} opening singleton class"
- end
- def self.eignclass
- class << self; self; end
- end
- puts "<<< " + self.to_s
- end
- class Class2
- puts ">>> " + self.to_s
- puts "#{self.__id__} before open singleton class"
- class << self
- puts "#{self.__id__} opening singleton class"
- end
- def self.eignclass
- class << self; self; end
- end
- puts "<<< " + self.to_s
- end
- puts "------------"
- puts "#{Class1.__id__} Class1.__id__"
- puts "#{Class1.eignclass.__id__} Class1.eignclass.__id__"
- puts "------------"
- puts "#{Class2.__id__} Class2.__id__"
- puts "#{Class2.eignclass.__id__} Class2.eignclass.__id__"
- puts "------------"
- c1 = Class1.new
- puts "#{c1.__id__} c1's id"
- class << c1
- puts "#{self.__id__} c1's singleton class"
- end
- puts "------------"
- c11 = Class1.new
- puts "#{c11.__id__} c11's id"
- class << c11
- puts "#{self.__id__} c11's singleton class"
- end
- puts "------------"
- c2 = Class2.new
- puts "#{c2.__id__} c2's id"
- class << c2
- puts "#{self.__id__} c2's singleton class"
- end
- puts "------------"
- c21 = Class2.new
- puts "#{c21.__id__} c21's id"
- class << c21
- puts "#{self.__id__} c21's singleton class"
- end
- # 実行結果
- # >>> Class1
- # 70227334526040 before open singleton class
- # 70227334526020 opening singleton class
- # <<< Class1
- # >>> Class2
- # 70227334525980 before open singleton class
- # 70227334525680 opening singleton class
- # <<< Class2
- # ------------
- # 70227334526040 Class1.__id__
- # 70227334526020 Class1.eignclass.__id__
- # ------------
- # 70227334525980 Class2.__id__
- # 70227334525680 Class2.eignclass.__id__
- # ------------
- # 70227334525100 c1's id
- # 70227334525040 c1's singleton class
- # ------------
- # 70227334524940 c11's id
- # 70227334524880 c11's singleton class
- # ------------
- # 70227334524780 c2's id
- # 70227334524720 c2's singleton class
- # ------------
- # 70227334524620 c21's id
- # 70227334524560 c21's singleton class