2012-08-28 79 views
2

我正在做一個herp-derpy的時刻。我敢發誓這工作:無法通過包含模塊來重新定義類的實例方法?

module StubbedGreeting 
    def sayit 
    puts "StubbedGreeting" 
    end 
end 

module RegularGreeting 
    def sayit 
    puts "RegularGreeting" 
    end 
end 

class Greeting 
    def sayit 
    raise "Gotta catch me!" 
    end 
end 

class GreetingIncludes 
    include RegularGreeting 
end 

begin 
    Greeting.send(:include, StubbedGreeting) 
    Greeting.new.sayit 
rescue Exception 
    puts "Exception raised" 
end 

GreetingIncludes.send(:include, StubbedGreeting) 
GreetingIncludes.new.sayit 

這裏會發生什麼事是Greeting.new.sayit導致在rescue塊被稱爲,無視StubbedGreeting企圖覆蓋。

但是,GreetingIncludes.new.sayit導致「StubbedGreeting」,不是一個例外。

因此,一個模塊可以覆蓋另一個模塊的方法,但沒有直接在類中定義的方法?

我知道如何擺脫這種困境,我發現它很奇怪。

回答

4

當包含一個模塊時,它的方法放在方法解析順序中的類的方法和它的父類之間。因此,在解決調用哪個實際方法時,ruby會首先按以下順序搜索該方法。如果找到匹配方法,則會中止搜索並使用此方法。

  • singleton類對象
  • 模塊包括到從最後的單個類的包括以第一包含
  • 該對象的類別
  • 模塊納入類

此的然後繼續每個父級,直到達到Class級。

如您所見,模塊確實不能覆蓋在類本身上定義的方法,因爲模塊在方法解析順序中落後於實際類。如果您確實需要重寫此方法,則可以使用alias_methodalias_method_chain來「重命名」方法。

在即將到來的Ruby 2.0中,將會有一個prepend mechanism,它將在類之前包含模塊,以達到您想要的效果。但它尚未發佈。

+0

很好的解釋,謝謝。 –

相關問題