Ruby 在扩展自身的模块中的实例方法中调用单例方法
我自己扩展了Ruby 在扩展自身的模块中的实例方法中调用单例方法,ruby,Ruby,我自己扩展了Kernel,在实例方法Kernel\abort的定义中,我调用了singleton方法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
Kernel
,在实例方法Kernel\abort
的定义中,我调用了singleton方法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
方法?内核。abort
是通过首先定义一个实例方法Kernel#abort
来定义的,然后使它也是一个带有模块(u
函数的单例方法。(;我在MRI源代码中找不到它,但请参见下文。)当您重新定义abort
时,您重新定义了实例方法,但没有定义单例副本
Object
包括Kernel
,因此当您说abort
时,您会得到实例方法,您已经重新定义了它,但是当您说Kernel.abort
时,您会得到单例方法,您还没有重新定义它
如果您确实想在abort
中使用递归,或者只是为了证明此解释是正确的,请在重新定义方法后调用module\u function:abort
。singleton方法将被更新为与instance方法相同,并且这两种方法都将递归
请注意,您不需要扩展self
来重新定义中止
的实例版本。由于内核
已包含在对象
中,因此只需重新定义所有对象的实例方法即可查看重新定义的版本。另一方面,如果Kernel
首先使用了extend self
来公开#abort
,我们就可以重新定义它,而不会出现任何复杂的情况
下面说明了用户定义的纯Ruby方法缺乏递归,也就是说,module\u function
负责,而本机方法不负责:
$ 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
你应该这样做:
module Kernel
class << self
alias :real_abort :abort
def abort
puts "press enter"
gets
puts "invoking real abort"
real_abort
end
end
end
在您提到的代码中,执行的中止不是Kernel.abort,而是从命令行调用时映射到IRB的C语言中止
如果您希望它被屏蔽,您可以这样做,以便IRB repl中的中止
将执行您重新定义的中止
def abort; Kernel.abort; end
然后,如果运行
abort
它将调用重新定义的内核的abort singleton方法。如果需要递归,请使用abort
而不是Kernel。abort
abort是一个隐式self
调用Kernel
在Kernel.abort
中,是显式的self
,指定应该调用方法的对象。哦,我重新打开了你的问题。@kimmmo:不,那里没有super
。@Daveschweiguth:doabort
而不是Kernel.abort
:)重新编辑最新的问题标题-我不确定它是否正确。这里没有课程,只有模块,对吗?谢谢。我将阅读所有3篇关于模块使用的文章,然后再回到这个问题。工作让我分心了,忘记了这个问题,对不起。我在回答中添加了一个例子,表明这种现象不是由于本地方法造成的。你能反驳我的回答并说它是错误的吗??
def abort; Kernel.abort; end