Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 在扩展自身的模块中的实例方法中调用单例方法_Ruby - Fatal编程技术网

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:do
abort
而不是
Kernel.abort
:)重新编辑最新的问题标题-我不确定它是否正确。这里没有课程,只有模块,对吗?谢谢。我将阅读所有3篇关于模块使用的文章,然后再回到这个问题。工作让我分心了,忘记了这个问题,对不起。我在回答中添加了一个例子,表明这种现象不是由于本地方法造成的。你能反驳我的回答并说它是错误的吗??
def abort; Kernel.abort; end