ruby中的方法尋找

來源:互聯網
上載者:User

標籤:style   blog   color   strong   問題   div   new   size   

  ruby中的方法調用都是 對象.方法 的形式,那麼對象如何找到這個方法呢?

  首先必須瞭解祖先鏈的概念,祖先鏈就是從一個類開始,到它的父類,再到父類的父類...一直到最終的起點(ruby中是BasicObject類)。這期間經曆過的路徑就是祖先鏈。

  1混含模組和繼承的方法尋找

  對於一個執行個體對象,先找它屬於的類中是否有對應的執行個體方法,然後看這個類中是否有模組,如果有,尋找模組中是否有對應的方法,如果沒有,則尋找父類。先看父類的執行個體方法,再看父類中是否有模組,再看父類的父類..一直到最後,BasicObject類和Kernel模組。

  如果還沒有,則會去查看method_missing函數,這個函數是內建函數。這個函數預設是報錯,當然你也可以重寫這個方法,來對沒有找到的方法在其中進行處理。

如下:

 1 module M 2     def method 3         puts "this is method in module M" 4     end 5 end 6  7 class C 8     include M 9 end10 11 class D < C;end12 13 D.new.method14 p D.ancestors

輸出是

this is method in module M
[D, C, M, Object, Kernel, BasicObject]

  如這個例子,類D的對象D.new要找method方法:先找D中的執行個體方法,沒有,D中也沒有模組。D的父類是C,先找C的執行個體方法,沒有,但C中有模組M,模組M中有method方法,這樣就找到了。這個順序就是按照祖先鏈的順序。

  這種尋找能到什麼程度呢?如祖先鏈表示的,接下來就是Object類,這是ruby中一切對象的開始。其中有一個模組Kernel。也就是說,如果你在Kernel中定義了一個方法,那麼ruby中的所有對象都可以用這個方法。

 

  2含有多個相同的方法時的方法尋找

  含有多個相同的方法時,會匹配第一個找到的方法。

如下:

 1 module M 2     def method 3         puts "this is method in module M" 4     end 5 end 6  7 module N 8     def method 9         puts "this is method in module N"10     end11 end12 13 class    C14     include M15     include N16 end17 18 C.new.method19 p C.ancestors

輸出結果

this is method in module N
[C, N, M, Object, Kernel, BasicObject]

  類C中包含兩個模組M和N,M和N都有method方法。那麼調用哪個呢?如果在同一個類中,ruby中新定義的方法會覆蓋舊的方法。類似的,模組N相對M是後混如類C的,所以會調用N中的方法。另一個方面,從祖先鏈來看,N也是排在M的前面,因此也是先調用N的方法。

  祖先鏈中是模組是怎麼排序的呢?祖先鏈中,一個模組M恰好在包含它的類C中的上一個位置。如這個例子,類C先包含了M,祖先鏈中是C,M。然後又包含了N,N又恰好在C的上一個位置,於是就變成了C,N,M。

 

  3包含單例類的方法尋找

  前面的兩種情況是不含單例類的情況,如果含有單例類,就要先考慮單例類了。

  單例類:簡單的說就是某個對象特有的類。它只能屬於一個對象(即使是同一個類的其他對象執行個體也不行),因此稱為單例類。

  ruby中的每個對象實際上都有兩個類:多個對象執行個體共用的類和單例類。對象調用的方法,就是這兩個類中的執行個體方法,以及祖先類和混含模組中的方法。

  有單例類的時候,對象的方法尋找先尋找單例類,然後是單例類混含的模組,然後是對象所屬的類,以此類推。

  單例類的父類是對象所屬的類。

如下:

 1 module M 2     def method 3         puts "this is method in module M" 4     end 5 end 6  7 class    C 8 end 9 10 c = C.new11 class << c12     def method13         puts "this is method in c‘ singleton class"14     end15     include M16     p ancestors17 end18 19 c.method

輸出是

[M, C, Object, Kernel, BasicObject]
this is method in c‘ singleton class

  單例類,並沒有在祖先鏈中表示出來,但是調用的方法確實是單例類的方法。然後是混含的模組M,然後是父類,以此類推。從祖先鏈可以看出,單例類的父類是C,是對象c所屬的類。

 

   HELP

  在這裡出現了一個問題,假如類C中也包含類別模組M,那祖先鏈理論上說應該是M,C,M,Object,Kernel,BasicObject

如下:

 1 module M 2 end 3 class    C 4     include M 5 end 6 c = C.new 7 class << c 8     include M 9     p ancestors10 end11 p C.ancestors

輸出結果是:

[C, M, Object, Kernel, BasicObject]
[C, M, Object, Kernel, BasicObject]

  單例類裡混含的模組沒有出現在祖先鏈裡,c的單例類和類C的祖先鏈一樣了。

 

  假設類C中包含的不是模組M,而是另一個模組N。

如下:

 1 module M 2 end 3 module N 4 end 5 class    C 6     include N 7 end 8 c = C.new 9 class << c10     include M11     p ancestors12 end13 p C.ancestors

輸出結果

[M, C, N, Object, Kernel, BasicObject]
[C, N, Object, Kernel, BasicObject]

  此時,結果和我預期的一樣。祖先鏈中仍然是有c的單例類混含的模組M的。

  這是為什麼呢?難道是說,如果單例類裡和祖先鏈上的其他類混含了同樣的模組,單例類中的模組名字不顯示了?

  另外我也在類Object中包含了M,結果是[C, N, Object, M, Kernel, BasicObject],c的單例類中的模組M也沒有。如果是包含N,結果是[M, C, N, Object, N, Kernel, BasicObject],又和預期的一樣。難道是單例類和祖先鏈上的其他類不能包含同樣的模組?

  我知道非單例類是可以包含同名的模組的,而且可以同時出現在祖先鏈裡。(我用的是ruby1.9.3)

  路過懂得求解答,不勝感激。

 

  4類方法的單例類

  上面講的是執行個體對象的單例類。如果是類的單例類呢?(每一個對象都有單例類,類也是對象,當然也有單例類,類方法就是放在單例類裡的。)

      單例類不能被繼承,但是單例類是可以有父類或者子類的。

如下:

 1 class C 2     def self.method 3         p "This is method in C" 4     end 5 end 6 class D < C 7 end 8 D.method 9 10 en = class << C;self;end11 class E < en;end;

輸出結果

"This is method in C"
can‘t make subclass of singleton class (TypeError)

  結果顯示,D.method調用的是C的單例方法,說明D的單例類繼承了C的單例類,是它的子類。但是從10-11行,可知,單例類是不能被繼承的。

  我覺得可以這麼認為:在D繼承C的時候,D的單例類繼承了C的單例類,所以D可以調用C的類方法。同理,D也可以調用Object類的類方法。

 

  整理一下:

  類的執行個體對象的方法尋找,先找單例類,然後單例類中的模組。再找父類,父類中的模組。以此類推。

  類對象的方法尋找,先找單例類(就是類方法),再找父類的單例類,以此類推。

  如果找到多個方法,以找到的第一個方法匹配。

  ruby中,一個類不能被繼承,它也可以有子類。例如ruby中類的單例類。

  如果我們用superclass來找父類的話,可得(#代表單例類,假設d是類D的對象,類D繼承類C,->表示父類是)

           #d->D->C->Object->BasicObject->nil

       #D->#C->#Object->#BasicObject->Class->Module->Object->BasicObject->nil

 

 

  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.