ruby中的方法查詢

2022-05-14 10:59:18 字數 4776 閱讀 9534

ruby中的方法呼叫都是物件.方法的形式,那麼物件如何找到這個方法呢?

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

1混含模組和繼承的方法查詢

對於乙個例項物件,先找它屬於的類中是否有對應的例項方法,然後看這個類中是否有模組,如果有,查詢模組中是否有對應的方法,如果沒有,則查詢父類。先看父類的例項方法,再看父類中是否有模組,再看父類的父類..一直到最後,basicobject類和kernel模組。

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

如下:

1

module m

2def

method

3 puts "

this is method in module m"4

end5

end6

7classc8

include m

9end

1011

class d 1213

d.new.method

14 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

2def

method

3 puts "

this is method in module m"4

end5

end6

7module n

8def

method

9 puts "

this is method in module n"10

end11

end12

13classc14

include m

15include n

16end

1718

c.new.method

19 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

2def

method

3 puts "

this is method in module m"4

end5

end6

7classc8

end9

10 c =c.new

11class

<12def

method

13 puts "

this is method in c' singleton class"14

end15

include m

16p ancestors

17end

1819 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

2end

3classc4

include m

5end

6 c =c.new

7class

<8include m

9p ancestors

10end

11 p c.ancestors

輸出結果是:

[c, m, object, kernel, basicobject]

[c, m, object, kernel, basicobject]

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

假設類c中包含的不是模組m,而是另乙個模組n。

如下:

1

module m

2end

3module n

4end

5classc6

include n

7end

8 c =c.new

9class

<10include m

11p ancestors

12end

13 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

classc2

defself.method

3 p "

this is method in c"4

end5

end6

class d 7end

8d.method

910 en = class

<11class 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

在Ruby中查詢和執行方法

當呼叫乙個方法時,ruby會做兩件事。1.找到這個方法。這個方法稱為方法查詢。2.執行這個方法。為了做到這點,ruby需要乙個叫做self的東西。這樣的乙個過程 發現乙個方法再執行之 在每種物件導向語言中都會發生。不過,對於像ruby這樣非常動態的語言,深入理解這個過程顯得尤為重要。你有沒有好奇過乙...

Ruby 中的inject方法

ruby inject 1 求和 inject 方法的兩種用法 enum.inject init value enum.inject第一種,result 以init value為初始值 第二種,result以element裡的第乙個元素為初始值。1,2,3,4 inject 0 10 1,2,3,4...

ruby中attr accessor方法的理解

attr accessor相當於attr reader和attr writer的合集,實際上是在定義類成員變數的時候就給他定義了乙個get和set方法。在ruby中,類成員變數都是私有的,不能直接通過 類名.成員變數名 這樣來對成員變數值進行操作。在這個例項中可以看到,使用attr accessor...