gpt4 book ai didi

ruby - 在扩展自身的模块中的实例方法中调用单例方法

转载 作者:数据小太阳 更新时间:2023-10-29 06:44:29 25 4
gpt4 key购买 nike

我自己扩展了Kernel,在实例方法Kernel#abort的定义中,我调用了单例方法Kernel.abort :

module Kernel
extend self

def abort
puts "Press ENTER to exit..."
gets
Kernel.abort
end
end

abort

当我调用 Kernel#abort 时,方法定义中的 Kernel.abort 调用似乎是指原始的 Kernel#abort (扩展为 Kernel.abort)。

Ruby 如何知道当我写 Kernel.abort 时,我指的是原始的 abort 方法,而不是我刚刚创建的方法?我将如何递归调用我刚刚创建的新 abort 方法?

最佳答案

Kernel.abort 的定义是首先定义一个实例方法 Kernel#abort ,然后用 module_function 使它也成为一个单例方法。 (This is definitely the case in Rubinius;我在 MRI 源中找不到它,但请参见下文。)module_function makes a copy of the method.当您重新定义 abort 时,您重新定义了实例方法而不是单例副本。

Object 包含 Kernel,所以当您说 abort 时,您会得到您重新定义的实例方法,但是当您说 Kernel.abort 你得到了你没有重新定义的单例方法。

如果您真的想在 abort 中使用递归,或者只是为了证明这个解释是正确的,请在重新定义方法后调用 module_function :abort。单例方法将更新为与实例方法相同,并且两种方法都将递归。

请注意,您不需要extend self 来重新定义abort 的实例版本。由于Kernel已经包含在Object中,所以你只需要重新定义所有对象的实例方法就可以看到重新定义的版本。另一方面,如果 Kernel 首先使用 extend self 来公开 #abort,我们可以重新定义它而不会出现任何复杂情况。

以下演示了用户定义的纯 Ruby 方法缺少递归,即 module_function 负责而 native 方法不是:

$ cat foo.rb
module Foo
def bar
puts "old version"
end
module_function :bar
end

module Foo
def bar
puts "new version"
Foo.bar
end
end

Object.include Foo
bar
$ ruby foo.rb
new version
old version

关于ruby - 在扩展自身的模块中的实例方法中调用单例方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35339860/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com