ruby - 获取对包含的 'Module' 的引用

标签 ruby

我的理解是,当一个模块被包含到一个类中时,会创建该模块的副本并将其放在包含类及其父类(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 the Professor module and uses it as the new superclass for Mathematician. Ruby's C source code refers to this copy of the module as an included class. The superclass of the new copy of Professor is set to the original superclass of Mathematician, 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/

相关文章:

ruby - Datamapper,定义自己的对象方法,怎么样?

ruby - 来自 ruby : JDBC connection to Sybase 的 sybase

ruby-on-rails - 查找两个条件都为真的所有记录

ruby - Nokogiri 无法从 svg 获取 g 标签

ruby-on-rails - Capistrano + Whenever gems - bin/rails : Permission denied

ruby-on-rails - belongs_to 关联中的第一个子元素是如何确定的?

ruby - 为什么我不能在方法中修改数组的值?

ruby-on-rails - ActiveRecord getter 中断验证

mysql - 使用 Ruby Sinatra 将 MySQL 数据库中的表显示到网站中

ruby-on-rails - Rails 使用逻辑运算符搜索 ActiveRecord