Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What is going on with this article?

More than 5 years have passed since last update.

@yui-knk

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

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

原則は

  • 特異クラスはクラスの前に呼び出される
  • 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の後に呼び出される。

9
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
9
Help us understand the problem. What is going on with this article?