首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kernel.require和Kernel.gem_original_require有什么区别?

Kernel.require和Kernel.gem_original_require有什么区别?
EN

Stack Overflow用户
提问于 2019-10-23 17:56:39
回答 1查看 107关注 0票数 1

考虑以下脚本:

代码语言:javascript
复制
module Kernel
  unless defined?(gem_original_require_2)
    alias gem_original_require_2 require
    private :gem_original_require_2
  end

  def require(path)
      return gem_original_require_2(path)
  end
end

p method(:require)                  # #<Method: main.require>
p method(:require).owner            # Kernel
p method(:require).receiver         # main
p method(:require).source_location  # ["1.rb", 7]

puts '-' * 10
p Kernel.method(:require)                  # #<Method: Kernel.require>
p Kernel.method(:require).owner            # #<Class:Kernel>
p Kernel.method(:require).receiver         # Kernel
p Kernel.method(:require).source_location  # nil

puts '-' * 10
p Kernel.method(:gem_original_require)                  # #<Method: Kernel.gem_original_require(require)>
p Kernel.method(:gem_original_require).owner            # Kernel
p Kernel.method(:gem_original_require).receiver         # Kernel
p Kernel.method(:gem_original_require).source_location  # nil

puts '-' * 10
p Kernel.method(:gem_original_require_2)                  # #<Method: Kernel.gem_original_require_2(require)>
p Kernel.method(:gem_original_require_2).owner            # Kernel
p Kernel.method(:gem_original_require_2).receiver         # Kernel
p Kernel.method(:gem_original_require_2).source_location  # ["/home/yuri/.rubies/ruby-2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb", 34]

我对输出有很多疑问。为什么Kernel有时是类,有时是模块?为什么他们有不同的接收器?当方法被调用时,receiver会变成self吗?

但更重要的是,Kernel.requireKernel.gem_original_require是同一种方法吗?Kernel.require 被重写。还有别的地方吗?如果你能回答剩下的问题,那就太棒了。

换句话说。让我们尝试用普通的类和方法来重现这个问题。正如在其他问题中所述,在Kernel上定义一个方法会创建两个方法(实例和单例)。所以:

代码语言:javascript
复制
class MyKernel
  # original require
  def require; puts 'require'; end
  def self.require; puts 'require'; end

  # copy original require
  alias gem_original_require require
  class << self
    alias gem_original_require require
  end
end

main = MyKernel.new

Kernel实际上是一个模块,但据推测,这在这里并不重要。

代码语言:javascript
复制
p MyKernel.method(:require)
  == MyKernel.method(:gem_original_require)
  # true

p main.method(:require)
  == main.method(:gem_original_require)
  # true

p main.method(:require)
  == MyKernel.method(:require)
  # false

因此,为了比较方法,您必须要么通过类访问它们,要么通过实例访问。让我们重写require

代码语言:javascript
复制
class MyKernel
  # override one of the original require's
  def require; puts 'require'; end
end

现在我们有了3个require

代码语言:javascript
复制
main.require (original)
MyKernel.require
main.require

和2个gem_original_requires:

代码语言:javascript
复制
main.gem_original_require
MyKernel.gem_original_require

我们可以比较类似(实例方法与实例方法,单例方法与单例方法)。但是我们不再能够访问原始的main.require,所以只剩下单例方法了。以下情况仍然有效:

代码语言:javascript
复制
p MyKernel.method(:require)
  == MyKernel.method(:gem_original_require)
  # true

但对于真正的require来说却不是

代码语言:javascript
复制
p Kernel.method(:require)
  == Kernel.method(:gem_original_require)
  # false
EN

回答 1

Stack Overflow用户

发布于 2020-03-31 19:19:01

我想你会在这里找到部分答案:https://stackoverflow.com/a/57236134/6008847

Rubygems代码替换了包含的require版本。

当您调用Kernel.require时,您将得到原始的require方法。

当您调用require时,您将从Rubygems获得该方法(接收方将是您调用require的上下文)。

gem_original_require是原始require方法的别名:require.rb#L16

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58528539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档