LoginSignup
12
9

More than 5 years have passed since last update.

[Ruby] オブジェクトのメソッド探索順序

Last updated at Posted at 2013-12-22

複雑な継承関係がある状態でオブジェクトのメソッドを呼び出すと、どのような順番でメソッドが呼び出されているかというお話。

原則は

  • 特異クラスはクラスの前に呼び出される
  • ModuleはincludeしたクラスやModuleの後に呼び出される
  • Moduleを複数includeすると後でincludeしたものが先に呼び出される

継承

class Parent
  def hello
    p "hello Parent"
    super
  end
end

class Child < Parent
  def hello
    p "hello Child"
    super
  end
end

Child.new.hello
# => 
"hello Child"
"hello Parent"
NoMethodError: super: no superclass method `hello' for #<Child:0x3eeccb0>

[Child, Parent]という順番。

Moduleをmixinする

module ModuleA
  def hello
    p "hello ModuleA"
    super
  end
end

module ModuleB
  def hello
    p "hello ModuleB"
    super
  end
end

module ModuleC
  def hello
    p "hello ModuleC"
    super
  end
end

class Parent
  include ModuleA
  def hello
    p "hello Parent"
    super
  end
end

class Child < Parent
  include ModuleB
  include ModuleC
  def hello
    p "hello Child"
    super
  end
end

Child.new.hello
# =>
"hello Child"
"hello ModuleC"
"hello ModuleB"
"hello Parent"
"hello ModuleA"
NoMethodError: super: no superclass method `hello' for #<Child:0x4556b98>

[Child, ModuleC, ModuleB, Parent, ModuleA]という順番。
Moduleはクラスのあとに呼び出される。複数のModuleをincludeしたときは、後からincludeされたものが先に呼び出される。

特異クラス

class Parent
  def hello
    p "hello Parent"
    super
  end
end

class Child < Parent
  def hello
    p "hello Child"
    super
  end
end

child = Child.new
def child.hello
  p "hello singleton Child"
  super
end

child.hello
# =>
"hello singlteon Child"
"hello Child"
"hello Parent"
NoMethodError: super: no superclass method `hello' for #<Child:0x3f0ce28>

[SingletonChild, Child, Parent]という順番。
特異クラスはクラスの前に呼び出される。

特異クラスでModuleを使う

module ModuleA
  def hello
    p "hello ModuleA"
    super
  end
end

class Parent
  def hello
    p "hello Parent"
    super
  end
end

class Child < Parent
  def hello
    p "hello Child"
    super
  end
end

child = Child.new
class << child
  include ModuleA
  def hello
    p "hello singlton Child"
    super
  end
end

child.hello
# =>
"hello singlton Child"
"hello ModuleA"
"hello Child"
"hello Parent"
NoMethodError: super: no superclass method `hello' for #<Child:0x34e2f10>

[SingletonChild, ModuleA, Child, Parent]という順番。
特異クラスはクラスの前に呼び出される。またModuleはincludeしたクラスの後に呼び出される。

Module内でModuleを使う

module ModuleA
  def hello
    p "hello ModuleA"
    super
  end
end

module ModuleB
  def hello
    p "hello ModuleB"
    super
  end
end

module ModuleC
  include ModuleA
  include ModuleB
  def hello
    p "hello ModuleC"
    super
  end
end

class Parent
  def hello
    p "hello Parent"
    super
  end
end

class Child < Parent
  include ModuleC
  def hello
    p "hello Child"
    super
  end
end

Child.new.hello
# =>
"hello Child"
"hello ModuleC"
"hello ModuleB"
"hello ModuleA"
"hello Parent"
NoMethodError: super: no superclass method `hello' for #<Child:0x393a968>

[Child, ModuleC, ModuleB, ModuleA, Parent]という順番。
ModuleはincludeしたModuleの後に呼び出される。

12
9
1

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
12
9