呼叫方法時發生了什麼?
呼叫方法時ruby會做兩件事:
(1)找到這個方法,這個過程成為方法查詢。
(2)執行這個方法,為了做到這點,ruby要用到乙個稱為self 的東西。
1.方法查詢
method lookup
呼叫乙個方法前,ruby會在物件中查詢那個方法。不過,在進一步學習之前,我們還要掌握兩個新概念:接受者(receiver)和祖先鏈(ancestors chain)。接受者就是你呼叫方法所在的物件。例如,在my_string.reverse()語句中,my_string就是接收者。為了理解祖先鏈 的概念,可以先觀察乙個ruby類。想像從乙個類找到它的超類,然後依次往上找,直到找到basicobject(ruby類體系結構的根節點)。在這個過程中,經歷的類的路徑就是該類的祖先鏈。(祖先鏈中可能會包含模組,後面再說。)
知道了接收者和祖先鏈,就可以用一句話來概括方法查詢的過程:ruby首先在接收者的類中查詢。然後順著祖先鏈向上查詢,直到找到這個方法為止。
class myclass
def my_method; 'my_method'; end
endclass mysubclass < myclass
end
obj = mysubclass.new
obj.my_method() # => "my_method()"
我們已經知道了祖先鏈是從類開始到其超類結束。 實際上,祖先鏈中也包含模組(module)。當吧一 個模組包含在乙個類(或者乙個模組)中時,ruby就會把這個模組加入該類的祖先鏈中,該模組在祖先鏈 中的位置就在包含它的類之上。
module m1
def my_method
'm1#my_method()'
endendclass c
inculde m1
endclass d < c; en
d.ancestors # => [d, c, m1, object, kernel, basicobject]
從ruby 2.0 開始,還可以用另外一種方法吧模組插入乙個類的祖先鏈中:使用prepend方法。 他的功能和include方法相似, 不過這個方法會把模組插入到祖先鏈中包含它的該類的下方,而不像include方法那樣插入上方:
class c2
prepend m2
endclass d2 < c2; end
d2.ancestors # => [d2, m2, c2, object, kennel, basicobject]
關於include和prepend,還有乙個重要的知識點。
多重包含
如果試圖在某個類的祖先鏈中多次加入同乙個模組,會如何呢?
module m1; end
module m2
include m1
endmodule m3
prepend m1
inculde m2
end
m3.ancestors # => [m1, m2, m3]
可以看出雖然我們多次的新增模組但是最後並沒有重複,每次include或者prepend的時候,如果該模組 已經存在於祖先鏈中, 那麼ruby會悄悄的忽略這個包含(include或prepend)指令。因此乙個模組只會在一條祖先鏈中出現一次。
無處不在的kernel模組
ruby中有一些方法(如print)可以隨時隨地的進行呼叫,看起來就像是所有物件都有print方法一樣。這是因為這些方法實際上都是kerenl模組的私有方法:
kernel.pricate_instance_methods.grep(/^pr/) # => [:printf, :print, :proc]
這裡的秘密在於object類包含了kernel模組,因此kernel模組就進入了每個物件的祖先鏈。於是,無論哪個物件都可以隨意呼叫kernel模組的方法。這使得print看起來就像乙個關鍵字,其實它只是乙個方法而已。 Ruby 元程式設計 第二版隨筆(三)
執行方法 method execution 呼叫方法時,ruby要做兩件事 首先找到這個方法,然後執行這個方法。到目前為止,我們只學會了如何找到這個方法,接下來看看如何執行方法。假設我們自己就是ruby直譯器,現在呼叫了乙個名叫my method的方法,我們先找到方法,發現該方法定義如下 def m...
GNU Linux程式設計指南 第二版
本書全面而深入地介紹了gnu linux程式設計。首先介紹了在linux上程式設計必備的程式設計工具,然後在庫函式 系統呼叫以及核心上闡述linux程式設計知識,並專門講述了包括tcp ip udp以及多播套介面在內的網路程式設計知識 圖形介面也是本書的重點內容,本書著重講述了文字形式的圖形介面庫n...
《演算法競賽入門經典(第二版)》 隨筆
c語言中整數值用 d輸出,實數 浮點數 用 f輸出。kiss原則 keep it and stupid 獲得程式執行時間 包括鍵盤輸入時間 include printf 執行時間 2f n double clock clocks per sec 輸入個數未知時 while scanf d x 1 對...