为什么在下面的代码片段中 foo 替换了它的定义?
def foo
def foo
1
end
end
第一次foo
是零
foo
=> nil
foo.foo
=> 1
现在,如果我foo
再打电话:
foo
=> 1
如您所见foo
,不再是 nil 了。谁可以给我解释一下这个?谢谢。
为什么在下面的代码片段中 foo 替换了它的定义?
def foo
def foo
1
end
end
第一次foo
是零
foo
=> nil
foo.foo
=> 1
现在,如果我foo
再打电话:
foo
=> 1
如您所见foo
,不再是 nil 了。谁可以给我解释一下这个?谢谢。
def foo
p "about to redef foo"
def foo
1
end
end
foo
"about to redef foo"
=> nil
foo
=> 1
此外,当您调用 时foo.foo
,似乎您正在尝试访问内部foo
方法,但它不起作用。您的foo
方法实际上是在 上定义的Object
,因此您实际上是在调用1.foo
.
如果你想要这个效果,试试
def foo
foo = proc {
1
}
end
由于def
方法不会创建新的self
. 每个方法都绑定到self
,main
在本例中是一个 Object.new ,它为 ruby 解释器加载的每个文件实例化。在一个类里面,self
就是类,你得到实例方法。
方法定义在读取时被解析,但在调用之前不会执行。当您执行第一个foo
时,执行最外层foo
,其定义Object#foo
为
def foo
1
end
并nil
作为定义该方法的操作的返回值返回。从此,当你调用 时foo
,新定义foo
的会被执行,返回
1
当你第一次调用foo
它返回方法foo
,当你再次调用foo
它返回 1。阅读闭包
ruby 中的嵌套方法定义令人困惑。
它们实际上是重新定义!
发生的情况是这两个定义都适用于最外层的上下文。那就是两个定义都定义了相同的(!)方法 foo。虽然外部定义在读取文件时被解释,而内部定义仅在第一次调用外部方法时被解释。然后它将替换初始定义。
鉴于此代码
def foo
def foo
1
end
end
让我们来看看:
foo
,使用 body 定义了一个全局方法def foo; 1; end
。当您调用foo()
此全局方法时,将执行并使用 body重新定义全局方法 ,并返回,因为定义方法没有返回值。foo
1
nil
当您调用foo().foo()
全局方法并返回时,再次1
执行全局方法,再次返回1
。
令人困惑的是两件事,a)嵌套方法定义都适用于相同的外部范围,b)可以在任何对象上调用全局方法。
这是另一个示例来演示嵌套定义实际上是如何重新定义的。
class A
def m(arg=nil)
def m; 42; end if arg
23
end
end
这就是发生的事情
a = A.new
a.m # => 23
a.m # => 23
a.m(:magic) # => 23
a.m # => 42
a.m # => 42
如您所见,嵌套定义实际上是重新定义。
就我个人而言,我一直认为它def
在类上定义了 inner 很奇怪。我认为在单例上定义它更明智。例如等效于def self.foo
,因为它是在实例级别而不是类级别调用的。
要么,要么它只能从它定义的方法中调用——尽管这可能没有那么有用,因为我们有 lambdas。
有一件事是肯定的,你几乎不会在实践中看到这一点。