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
如何处理模块的祖先。