類(lèi)的補(bǔ)丁
本章節(jié)中會(huì)為大家介紹如何為類(lèi)打一個(gè)補(bǔ)丁,拓展類(lèi)的方法以及了解“猴子補(bǔ)丁“,如何避免“猴子補(bǔ)丁”。
1. 為類(lèi)打一個(gè)補(bǔ)丁
我們通過(guò)之前的學(xué)習(xí)了解了,如何去定義一個(gè)類(lèi)。
class C
puts "Hello"
end
# ---- 輸出結(jié)果 ----
Hello
Ruby 中類(lèi)定義的語(yǔ)句和其他語(yǔ)句本質(zhì)是一樣的,我們現(xiàn)在使用 3.times
來(lái)迭代定義類(lèi) C。
3.times do
class C
puts "Hello"
end
end
# ---- 輸出結(jié)果 ----
Hello
Hello
Hello
這并不意味著我們可以定義三個(gè)同樣名字為 C 的類(lèi),類(lèi)只有第一次被創(chuàng)建,之后我們只是打開(kāi)了這個(gè)類(lèi),并追加了一些內(nèi)容給這個(gè)類(lèi)。
class D
def x
'x'
end
end
class D
def y
'y'
end
end
obj = D.new
puts obj.x
puts obj.y
# ---- 輸出結(jié)果 ----
x
y
解釋:當(dāng)?shù)谝淮翁峒?code>class D的時(shí)候,我們還沒(méi)有類(lèi) D,所以我們定義了類(lèi) D,并增加了一個(gè)x
方法。當(dāng)?shù)诙翁峒?code>class D的時(shí)候,我們已經(jīng)創(chuàng)建了類(lèi) D,就不會(huì)再次定義了,只是重新打開(kāi)這個(gè)類(lèi) D,并給它定義了y
方法。
Tips:您甚至可以修改 Array 和 String 這些類(lèi),為這些類(lèi)增加補(bǔ)丁。
2. 猴子補(bǔ)丁
如果您為某一個(gè)類(lèi)添加了一個(gè)新功能,導(dǎo)致這個(gè)類(lèi)本身的功能受到影響,那么這個(gè)導(dǎo)致 bug 的補(bǔ)丁被稱(chēng)為猴子補(bǔ)丁(Monkeypatch)。
我們都知道,Integer
擁有一個(gè)實(shí)例方法名叫 to_s
,它可以將整型對(duì)象變?yōu)樽址畬?duì)象。
實(shí)例:
1.to_s
# ---- 輸出結(jié)果 ----
'1'
若是我們給它打一個(gè)猴子補(bǔ)丁,那它原有的方法就會(huì)失效。
實(shí)例:
class Integer
def to_s
self # 返回本身
end
end
1.to_s
# ---- 輸出結(jié)果 ----
1
解釋:因?yàn)?code>Integer已經(jīng)存在了to_s
的方法,我們新定義的to_s
方法會(huì)覆蓋原有的方法。
注意事項(xiàng):誤用了猴子布丁會(huì)導(dǎo)致異常的發(fā)生,但是有時(shí)候,我們希望改造已有類(lèi)庫(kù)的時(shí)候,會(huì)有意去使用它。因?yàn)樗婕暗饺中缘男薷?,而且一單出現(xiàn)問(wèn)題很難追蹤。所以在為某個(gè)類(lèi)的時(shí)候需要檢查這個(gè)類(lèi)是否有同名的方法,如果需要增加補(bǔ)丁,一定優(yōu)先創(chuàng)建一個(gè)新方法。
3. 小結(jié)
本章節(jié)我們學(xué)習(xí)了如何給類(lèi)打補(bǔ)丁,猴子補(bǔ)丁是什么。