我的理解是,当一个模块被包含到一个类中时,会创建该模块的副本并将其放在包含类及其父类(super class)之间。 让我引用 Pat Shaughnessy 的显微镜下的 ruby 。假设您有以下内容:
module Professor
end
class Mathematician < Person
include Professor
end
When we run the above code, Ruby creates a copy of the
RClass
structure for theProfessor
module and uses it as the new superclass forMathematician
. Ruby's C source code refers to this copy of the module as an included class. The superclass of the new copy ofProfessor
is set to the original superclass ofMathematician
, which preserves the superclass, or ancestor chain.
是否可以获得对包含的类的引用?例如,我想获取对 Object
类中包含的 Kernel
模块的引用。
最佳答案
My understanding is that, when a module is included into a class, a copy of the module is made and put between the including class and its superclass.
从 Ruby 的角度来看,没有进行任何复制。一个引用被添加到祖先中,就是这样。
您的问题中描述的行为(摘自 "Ruby under a microscope" )可能特定于 CRuby。在内部,Ruby 模块被保存为修改后的RClass
,并在包含该模块时创建一个副本。 Rubinius中似乎并非如此例如。我也不认为可以访问引用 Ruby 中包含的模块的复制的内部 RClass
。
您可以通过这种方式检查 Ruby 行为:
module M
def copy_or_reference?
puts "copy!"
end
end
class A
include M
end
class B
include M
end
m2 = A.included_modules.first
m2.send(:define_method, :copy_or_reference?) { puts "reference!" }
B.new.copy_or_reference?
#=> reference!
我们从 A
的祖先中提取 M
模块。我们在这个祖先模块中重新定义了 copy_or_reference?
方法。如果它是原始 M
模块的副本,则从 B
实例调用的 M#copy_or_reference?
仍会返回 “复制!”
。
要获取包含的模块,您还可以使用:
A.ancestors.grep_v(Class)
在 Ruby 2.3+ 或
A.ancestors.reject{ |o| o.is_a?(Class) }
在旧版本中。
如果您想了解更多信息,可以尝试 ping @JörgWMittag .
关于ruby - 获取对包含的 'Module' 的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45070048/