#概要
Rubyの特異メソッドについてまとめました。
#特異メソッドとは?
特異メソッドとは1つのインスタンス固有のメソッドのことを指します。
特定のインスタンスに特別な性質を持たせたい場面に活躍します。
特異メソッドはdef オブジェクト名.メソッド名
で定義できます。
#実例
以下のコードにおいてMovie
クラスから作成された2つのインスタンスobj1
,obj2
の両方がクラス内のインスタンスメソッドi_method
を実行可能です。
しかし、obj1.s_method
の形で定義されたs_method
はobj1
のみでしか実行できません。
これはs_method
はobj1
のみが持つ特異メソッドとして定義されているからです。
class Movie
def i_method
p 'instance method'
end
end
obj1 = Movie.new
obj2 = Movie.new
def obj1.s_method
p 'singlton method'
end
obj1.i_method #=> 'instance method'
obj2.i_method #=> 'instance method'
obj1.s_method #=> 'singlton method'
obj2.s_method #=> undefined method `s_method' for #<Movie:0x00007fc2fc842c38> (NoMethodError)
特異メソッドとは何か、どのように定義するか理解しました。
そこで終わらず、特異メソッドはどんな仕組みで実現されているのかまで理解します。
#特異メソッドの正体
上記のようにdef オブジェクト名.メソッド名
でメソッドを定義するとRubyインタプリンタは特異クラス(特定のオブジェクト固有のクラス)と呼ばれるクラスを作成して継承チェーンに組み込みます。
ですので、実態としてはこの特異クラスに定義されているメソッドが特異メソッドであり、それ故に特異クラスに対応した特定のオブジェクト以外はそのメソッドを実行できないということになります。
オブジェクトが持っている特異クラスはObject#singleton_class
メソッドによって確認する事ができます。
class Movie
def i_method
p 'instance method'
end
end
obj1 = Movie.new
def obj1.s_method
p 'singlton method'
end
p obj1.class.method_defined?(:s_method) #=> false
p obj1.singleton_class.method_defined?(:s_method) #=> true
以上の例からもs_method
はMovieクラス
には定義されておらず、特異クラス内に定義されている事がわかります。
#注意点
上記で特定のオブジェクト固有のクラスを作成すると表記しましたが、特異クラスに対応するインスタンスは、特異クラスが生成された後も生成元をスーパークラスとして指します。
これは特異クラスはあくまでもインタプリタの内部で使用するクラスであり、__ユーザーに意識させたくないクラス__であるためです。
class Movie
def i_method
p 'instance method'
end
end
obj1 = Movie.new
def obj1.s_method
p 'singlton method'
end
p obj1.class #=> Movie
#生成元のMovieを返す。
p obj1.instance_of?(Movie) #=> true
#Movieクラスのインスタンスであるか試すとtrueが返る。
SClass = obj1.singleton_class
p obj1.instance_of?(SClass)
#シングルトンクラスのインスタンスであるか試すとfalseが返る。