LoginSignup
2
3

More than 5 years have passed since last update.

method_missingの探索はどこから始まるのか?

Last updated at Posted at 2017-02-25

method_missingはBasicObjectまでメソッド探索を行ってもメソッドが見つからなかったときに呼び出されるメソッドで例えば以下のようなクラスが定義されている場合、Cクラスのインスタンスで存在しないno_existを呼び出すと

  1. (インスタンスの特異クラス)→C→B→A→...BasicObjectまでundefined_methodが探索されるが見つからない。
  2. (インスタンスの特異クラス)→C→B→A→...BasicObjectまでmethod_missingを探索し、BasicObjectに定義されているmethod_missingが呼ばれてNoMethodErrorが発生する。
class A
end

class B < A
end

class C < B
end

>  C.ancestors
=> [C, B, A, Object, Kernel, BasicObject]
>  C.new.undefined_method
NoMethodError: undefined method `no_exist' for #<C:0x007ffaa2a28948>

なので例えば以下のようにCクラスにmethod_missingを定義することでCクラスに対するMethodMissing例外を捕捉することが出来ます。

class A
end

class B < A
end

class C < B
  def method_missing(m)
    "ignore #{m}"
  end
end

> C.new.undefined_method
=> "ignore no_exist"

今度はBクラスに対してもmethod_missingを定義します。するとCクラスのインスタンスからno_existを呼び出したときはCによって捕捉され、Bクラスのインスタンスから呼び出したときはBによって捕捉されています。このことからmethod_missingの探索開始地点はメソッドを呼び出したレシーバから始まっていることがわかります。

class A
end

class B < A
  def method_missing(m)
    "ignore #{m} by B"
  end
end

class C < B
  def method_missing(m)
    "ignore #{m} by C"
  end
end

> B.new.undefined_method
=> "ignore no_exist by B"
> C.new.undefined_method
=> "ignore no_exist by C"

では以下のようにCクラスのインスタンスから、Bクラスのメソッドが呼び出されてそのメソッド内で存在しないメソッドが呼び出された場合はどうなるでしょうか?

class A
end

class B < A
  def baz
    undefined_method
  end
  def method_missing(m)
    "ignore #{m} by B"
  end
end

class C < B
  def method_missing(m)
    "ignore #{m} by C"
  end
end

> C.new.baz
C
=> "ignore undefined_method by C"

一瞬Bクラスのメソッドから存在しないメソッドを呼び出しているのでBクラスから探索が始まりそうに思ってしまいますが、この場合もあくまでもno_existメソッドはCクラスのインスタンスをレシーバとして呼び出されているのでCクラスから探索が始まります。

なので例えば以下のように書けばBクラスから探索が始まります

class A
end

class B < A
  def baz
    B.new.undefined_method
  end
  def method_missing(m)
    "ignore #{m} by B"
  end
end

class C < B
  def method_missing(m)
    "ignore #{m} by C"
  end
end

> C.new.baz
=> "ignore undefined_method by B"

結局結論はとてもシンプルで
存在しないメソッドを呼び出したレシーバから探索は始まる
でした。

2
3
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
2
3