我有一个狡猾的时刻。我可以发誓这有效:
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”,而不是例外。
所以一个模块可以覆盖另一个模块的方法,但不能直接在类中定义方法吗?
我知道如何在这方面找到方法,我发现它很奇怪。
答案 0 :(得分:4)
当包含模块时,它的方法放在类的方法和方法解析顺序中的父类之间。因此,在解析要调用的实际方法时,ruby首先按以下顺序搜索方法。如果找到匹配方法,则中止搜索并使用此方法。
然后继续为每个父类继续,直到达到Class
类。
正如您所看到的,模块确实不能覆盖类本身定义的方法,因为模块在方法解析顺序中位于实际类的后面。如果您确实需要覆盖此类方法,则可以使用alias_method
或alias_method_chain
来“重命名”方法。
在即将发布的Ruby 2.0中,将会有一个prepend mechanism,它将在课程之前包含模块,以实现您想要的目标。但它还没有发布。