0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[ Ruby ] 特異メソッドと特異クラス

0
Posted at

はじめに

特異クラス、特異メソッドについて、ふと調べてみようと思ったので、その内容をまとめてみます。

特異メソッド

オブジェクト固有のメソッドのことです。
定義するメソッド名の前に、オブジェクト名を書くことで定義できます。
なお、定義する際に、そのオブジェクトが既に存在していないといけません。

class Klass
end

apple = Klass.new
orenge = Klass.new

def apple.tokui_method
  puts "I'm apple"
end

apple.tokui_method
# => I'm apple
orenge.tokui_method
# => undefined method `tokui_method'

もしも定義する際にその指定するオブジェクトが存在していなかった場合、エラーとなります。

class Klass
end

def apple.tokui_method
  puts "I'm apple"
end

apple = Klass.new

apple.tokui_method
# => undefined local variable or method `apple' for main:Object (NameError)

特異メソッド内でsuperを呼ぶと、クラスに定義されている同名のメソッドが呼ばれます。
また、そのメソッドのオーバーライドが出来るという便利な点もあります。

class Klass
  def my_name
    puts "I'm fruits"
  end
end

apple = Klass.new
orenge = Klass.new

def apple.my_name
  super
  puts "I'm apple"
end

apple.my_name
# => I'm fruits
# => I'm apple
orenge.my_name
# => I'm fruits

特異クラス

あるオブジェクトに特異メソッドを定義した際に、そのメソッドが定義されるクラスが特異クラスです。

通常のクラスとは違い、特異クラスはあるオブジェクトだけが使用するクラスです。
そのため、特異クラスからオブジェクトを作成したり、サブクラスを作成することは禁止されています。

オブジェクトの特異クラスを確認するには
Object#singleton_classを使用します。

class Klass
end

obj = Klass.new
# => #<Klass:0x00007f8fb584cc08>

TokuiClass = obj.singleton_class
# => #<Class:#<Klass:0x00007f8fb584cc08>>

TokuiClass.new
# => can't create instance of singleton class (TypeError)

class SubTokuiClass < TokuiClass
end
# => can't make subclass of singleton class (TypeError)

また、前述した特異メソッドは特異クラスに定義されています。
特異メソッドに関しては
singleton_class.method_defined?で確認することができます。

class Klass
end

obj = Klass.new

def obj.tokui_method
  :tokui_method
end

p obj.class.method_defined? :tokui_method
# => false
p obj.singleton_class.method_defined? :tokui_method
# => true

特異クラスが作成されるタイミング

オブジェクトが生成されたタイミングでは、そのオブジェクトの特異クラスは存在していません。
特異クラスは以下の場合に作成されます。

1, 特異メソッドを定義するタイミング
2, 特異クラス定義式を評価したタイミング
3, Object#singleton_classでオブジェクトに対して特異クラスの確認をするタイミング

特異メソッドを定義するタイミング
obj = Klass.new

def obj.tokui_method
  :tokui_method
end
特異クラス定義式を評価したタイミング
class << obj
end
Object#singleton_classでオブジェクトに対して特異クラスの確認をするタイミング

確認しようとしたタイミングで、特異クラスが存在していなければ新たに作成されます。

obj.singleton_class

オブジェクトと特異クラス

特異クラスは、オブジェクトのクラスのサブクラスになります。

class Klass
end

obj = Klass.new
obj.singleton_class.supperclass
# => Klass

特異クラスがあるオブジェクトに対して作成されると、そのオブジェクトは特異クラスのインスタンスになりますが、Rubyの中では
特異クラスのインスタンスであるということは無視されるようになっており、常にオブジェクトのクラスのインスタンスとして扱われます。
Object#instance_of?で引数の直接のインスタンスか確認できるため、これを使用してみます。

obj.instance_of? obj.singleton_class
# => false

obj.instance_of? Klass
# => true

特異クラスをもてないオブジェクト

Rubyで以下のオブジェクトは特異クラスを持つことが出来ません。

  • 数値
  • Symbol
  • true, false, nil
整数とsymbleはエラーが返ってきます
1.singleton_class
# => can't define singleton (TypeError)
:symble.singleton_class
# => can't define singleton (TypeError)
true, false, nil は自身のクラスが特異クラスとして返ってきます
p true.singleton_class
# => TrueClass

p false.singleton_class
# => FalseClass

p nil.singleton_class
# => NilClass
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?