2011-06-13 29 views
2
module Lab 
    def self.foo 
    puts 'foo from lab' 
    end 
end 

module M 
    def foo 
    puts 'foo from module' 
    super 
    end 
end 

module Lab 
    extend M 
end 

Lab.foo 

我期待,我會看到爲什麼要擴展方法是不把看跌期權價值

foo from module 
foo from lab 

但是我所得到的是

foo from lab 

我所試圖做的是攔截一個來自寶石的方法的價值,並做一些事情。我可以使用alias_method_chain,但我試圖不使用它。

+0

我刪除我的答案,因爲這是不正確的(出於某種原因,人們反正upvoting它)。爲了防止人們思考我的想法:上述代碼中的方法都不是實例方法(因爲「擴展」的工作原理)。 – 2011-06-13 23:40:03

回答

0

當包括/擴展模塊M一類C,並調用一個方法或C#methodC.method,其也爲M所定義,然後在C在該方法的搜索路徑M具有優先權。換句話說,你不能用include/extend覆蓋方法。您只能添加新的方法。請參閱this相關問題。

在你的情況下,簡單地調用Lab.foo。以下(沒有Lab.foo)會給你想要的結果。

module M 
    def foo 
    puts 'foo from module' 
    end 
end 

module Lab 
    extend M 
end 

Lab.foo 

# => foo from module 

請注意,您的M的超類是Module,由於Module#foo沒有定義,下面會導致錯誤。

module M 
    def foo 
    puts 'foo from module' 
    super 
    end 
end 

module Lab 
    extend M 
end 

Lab.foo 

# => method undefined error 
1

如果你期待

foo from module 
foo from lab 

然後,你需要把超級在實驗室#FOO,就像這樣:

module Lab 
    def self.foo 
    super 
    puts 'foo from lab' 
    end 
end 

module M 
    def foo 
    puts 'foo from module' 
    end 
end 

module Lab 
    extend M 
end 

Lab.foo 
1

Lab定義的直接與優先的方法Lab延伸的模塊中定義的方法如M

因此,直接在Lab上定義的foo優先於M#foo,即使Lab.extend M

爲了得到你想要的東西,這樣做:

module Lab 
    module HasFoo 
    # foo isn't defined directly on Lab directly anymore; 
    # instead, it is defined in a separate module that 
    # Lab extends 
    def foo 
     puts "foo from lab" 
    end 
    end 

    extend HasFoo 
end 

module M 
    def foo 
    puts "foo from module" 
    super 
    end 
end 

module Lab 
    # when Lab extends another module with foo, that changes 
    # which concrete method the name foo gets resolved to 
    extend M 
end 

# now you should see the module foo and then the lab foo 
Lab.foo 
相關問題