我有这段代码:
module M
def m
"hello"
end
end
include M
m # => hello
M.m # => hello
将M
添加到顶层,我可以致电m
。为什么我可以致电M.m
?
答案 0 :(得分:4)
在顶层调用include M
包括Object
中的模块:
module M
def m
"hello"
end
end
include M
Object.included_modules #=> [M, Kernel]
您可以通过以下方式实现相同目标:
class Object
include M
end
因为Ruby中的所有内容都是对象,所以您可以将m
发送到每个对象 1 ,包括实例,类和模块(如M
):
123.m #=> "hello"
'foo'.m #=> "hello"
String.m #=> "hello"
Object.m #=> "hello"
Enumerable.m #=> "hello"
M.m #=> "hello"
1 is_a? Object
答案 1 :(得分:1)
"默认定义" (即,def
和include
d mixins定义的方法结束的模块)在顶层是Object
。
这意味着M
被包含在Object
中,即M
成为Object
的超类,插入Kernel
下方。由于M
是模块的实例,而Module
是Object
的子类,而Object
现在是M
的子类,因此可以调用{ {1}}。
M.m
的祖先链是:
Module
ergo,[Module, Object, M, Kernel, BasicObject]
位于M
的方法查找路径中,因此M
找到M.m
中定义的方法。
答案 2 :(得分:0)
更奇怪的例子:
▶ module M ; end
▶ def m ; puts '¡Hola!' ; end
#⇒ :m
▶ M.m
#⇒ ¡Hola!
所以,让我们深入研究对象继承。执行上下文是main
。 main
显然是Object
的“特殊”实例,传播其上定义的所有方法,随处可见。由于Module
实例(M
)实际上是Object
的实例,因此它会突然响应每个Object
方法。但我们只使用Object
方法扩展了m
。
注意:顶级module M ; def m ; end ; end; include M
和def m ; end
几乎完全相同:都使用Object
方法扩展m
(后者使此方法{{1}但是在private
上。)
希望它有所帮助。