此篇文章將探討Ruby 如何呼叫方法
開始說明流程之前,如果有對 self 不太暸解的話,
可以先看一下昨天的文章Day 6 -- What is Self in Ruby's World ?
在 Metaprogramming Ruby 書中,當程式呼叫方法時,Ruby會做 2 件事情:
乍看之下似乎很簡單,但卻有不少的幕後工作是默默地執行。
要介紹 method lookup 之前,先需要了解什麼是 "receiver(接收者)" 以及 "ancestors chain" 。
Receiver 就是當你呼叫方法時的接收者,例如:在先前提過的 obj.my_name('kevin') ,obj 就是 my_name()方法的 receiver。
Ancestors chain 或許可以想像成是家族的族譜,意思是從找到 '接收者' 的 class 後,開始持續往上找父層,ㄧ直到最上層 (BassicObject) 為止。
來看以下的圖會更清楚:
class Animal
def run
@str = "running"
end
end
class Cat < Animal
def speak
"meow"
end
end
kitty = Cat.new
kitty.run # => "running"
kitty.instance_variables # => [:@str]
kitty.class.instance_methods(false) # => [:speak]
kitty.class.instance_methods(true) # => [:speak, :run, :to_yaml...]
黃金法則:ㄧ步往右,再往上 "One step to the right, then up"
當 run() 方法被呼叫時,會先去找 run() 的接受者(receiver),也就是 kitty 物件(object)。接者會依著ㄧ個指向屬於CLASS的連結,往右找尋到 Cat 類別(Class),但是 Cat 類別裡沒有 run() 方法,因此再繼續往上層找,直到 run() 方法被找到為止。
Cat.ancestors # => [Cat, Animal, Object, Kernel, BasicObject]
"One step to the right, then up"
物件呼叫方法時,先判斷 Receiver 為何?找到之後先往右一步,再往上找