2011-06-13 27 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 
相关问题