Ruby 是如何隐式地允许类外部的类访问方法的?
例子:
class Candy
def land
homer
end
end
def homer
puts "Hello"
end
Candy.new.land #Outputs Hello
“homer”方法的定义是将方法添加到 Object 类中。它没有定义自由功能。
Candy 类隐式继承自 Object,因此可以访问 Object 中的方法。当你在“land”方法中调用“homer”时,方法解析在当前类中找不到定义,去超类,找到你添加到Object的方法,并调用它。
一个简单的方法来找出发生了什么
搜索哪些类/模块来解析 Candy 对象中使用的方法?
p Candy.ancestors #=> [糖果、对象、内核]
Candy 有叫做 homer 的方法吗?
p Candy.instance_methods(false).grep("homer") #=> []
p Candy.private_instance_methods(false).grep("homer") #=> []
OK Candy 没有任何名为“homer”的方法。
查找链中的下一步是什么(参见 1)=>“对象”
Object 是否有一个名为“homer”的方法?p Object.instance_methods(false).grep("homer") #=> []
p Object.private_instance_methods(false).grep("homer") #=> ["homer"]
Candy 在其查找链中有对象,而对象又具有私有实例方法“homer”,因此方法解析成功
def 语句总是在定义点定义 self 的类中的方法
定义 homer 之前的self是什么?
p self #=> main def homer 将“Hello”结束
那么它的类型是什么?
p self.class #=> 对象
这就是为什么本垒打最终出现在Object上的原因
从技术上讲,homer
方法的定义实际上是在Kernel
混入的模块上Object
,而不是Object
直接在模块上。所以当homer
不是定义在 上的局部变量或实例方法时Candy
,Ruby 方法继承链会跟进Object
,然后到混入Kernel
模块,然后运行这段代码。
编辑:对不起,我不知道我为什么这么想。看来该方法确实存在Object
。不确定它在实践中是否有太大的不同,但我应该在发布之前确认一下。
Ruby 没有自由浮动函数。每个方法都属于某个对象。您def
在顶层的方法实际上正在成为 class 的实例方法Object
。因为一切都Object
在某种程度上,所有对象都可以访问Object
的实例方法。