LoginSignup
28

More than 3 years have passed since last update.

【Ruby】特異メソッド・特異クラスを理解する

Last updated at Posted at 2018-06-28

概要

Rubyの特異メソッドについてまとめました。

特異メソッドとは?

特異メソッドとは1つのインスタンス固有のメソッドのことを指します。
特定のインスタンスに特別な性質を持たせたい場面に活躍します。
特異メソッドはdef オブジェクト名.メソッド名で定義できます。

実例

以下のコードにおいてMovieクラスから作成された2つのインスタンスobj1,obj2の両方がクラス内のインスタンスメソッドi_methodを実行可能です。
しかし、obj1.s_methodの形で定義されたs_methodobj1のみでしか実行できません。
これはs_methodobj1のみが持つ特異メソッドとして定義されているからです。

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_methodMovieクラスには定義されておらず、特異クラス内に定義されている事がわかります。

注意点

上記で特定のオブジェクト固有のクラスを作成すると表記しましたが、特異クラスに対応するインスタンスは、特異クラスが生成された後も生成元をスーパークラスとして指します。
これは特異クラスはあくまでもインタプリタの内部で使用するクラスであり、ユーザーに意識させたくないクラスであるためです。

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が返る。

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
28