Ruby,向模块、类或对象添加方法

Ruby,向模块、类或对象添加方法,ruby,Ruby,当我向内核添加方法以使它们全局可用时,我注意到了一些奇怪的事情。这很有趣,我正在寻找一些文档或很好的解释 让我们看看代码: 文件:./demo.rb # example 1 module Kernel def foo puts "I'm defined inside the module!" end end # example 2 module Bar def bar puts "I'm included! (bar)" end end Kernel.s

当我向
内核添加方法以使它们全局可用时,我注意到了一些奇怪的事情。这很有趣,我正在寻找一些文档或很好的解释

让我们看看代码:

文件:./demo.rb

# example 1

module Kernel
  def foo
    puts "I'm defined inside the module!"
  end
end


# example 2

module Bar
  def bar
    puts "I'm included! (bar)"
  end
end

Kernel.send :include, Bar


# example 3

module Baz
  def baz
    puts "I'm included! (baz)"
  end
end

module Kernel
  include Baz
end
然后,在bash和IRB中

$ irb -r ./demo.rb
> foo
# I'm defined inside the module!
> bar
# NameError: undefined local variable or method `bar' for main:Object
> baz
# NameError: undefined local variable or method `baz' for main:Object
>
> self.class.ancestors
# => [Object, Kernel, BasicObject] 
>
> include Kernel
>
> self.class.ancestors
# => [Object, Kernel, Baz, Bar, BasicObject]
>
> foo
# I'm defined inside the module!
> bar
# I'm included! (bar)
> baz
# I'm included! (baz)
foo
按预期工作,可用于包含
内核的所有对象<另一方面,条形码和baz不能立即使用。
我想这是因为IRB(一个
对象
)的评估上下文已经包含
内核
,并且在模块B中包含模块a不会“重新加载”B之前包含的所有内容。
好的,这很有意义,事实上,重新包含
内核将添加另外两个方法

那么我的问题是:

  • 为什么要打开
    内核
    呢?(例1)
  • 如果打开模块的方式不同,为什么第三个示例不起作用

  • 在Ruby中调用
    foo.bar
    会发生什么?大概是这样的:

    foo.class.ancestors.each do |klass|
      if klass.public_instance_methods.include? :bar
        return klass.instance_method(:bar).bind(foo).call
      end
    end
    raise NameError
    
    B.ancestors.each do |mod|
      A.ancestors << mod unless A.ancestors.include? mod
    end
    
    i、 Ruby搜索祖先以找到匹配的实例方法

    在Ruby中调用A.include B时会发生什么?大概是这样的:

    foo.class.ancestors.each do |klass|
      if klass.public_instance_methods.include? :bar
        return klass.instance_method(:bar).bind(foo).call
      end
    end
    raise NameError
    
    B.ancestors.each do |mod|
      A.ancestors << mod unless A.ancestors.include? mod
    end
    
    B.concenters.each do|mod|
    
    谢谢。很清楚,这正好解决了我的疑问。你知道关于这种行为有什么好的资源吗?或者我应该使用来源,卢克?解释了其中的一些内容,但我确实必须挖掘源代码,以了解
    include
    如何处理模块的祖先。