为啥在 Ruby 中包含模块的顺序会有所不同?

Posted

技术标签:

【中文标题】为啥在 Ruby 中包含模块的顺序会有所不同?【英文标题】:Why does the order of including modules make a difference in Ruby?为什么在 Ruby 中包含模块的顺序会有所不同? 【发布时间】:2010-09-25 02:45:46 【问题描述】:

这个问题最好用一个代码示例来概括:

module TestOne
  module Foo
    def foo
      42
    end
  end

  module Bar
    include Foo
  end

  class Quux
    include Bar
  end
end

TestOne::Bar.ancestors # => [TestOne::Bar, TestOne::Foo]
TestOne::Quux.ancestors # => [TestOne::Quux, TestOne::Bar, TestOne::Foo, Object, Kernel]
TestOne::Quux.new.foo # => 42

module TestTwo
  class Quux
  end

  module Bar
  end

  module Foo
    def foo
      42
    end
  end
end

TestTwo::Quux.send :include, TestTwo::Bar
TestTwo::Bar.send :include, TestTwo::Foo

TestTwo::Bar.ancestors # => [TestTwo::Bar, TestTwo::Foo]
TestTwo::Quux.ancestors # => [TestTwo::Quux, TestTwo::Bar, Object, Kernel]
TestTwo::Quux.new.foo # => 
# ~> -:40: undefined method `foo' for #<TestTwo::Quux:0x24054> (NoMethodError)

我认为当你包含一个模块时(例如 Bar 在类 Foo 中),Ruby 存储的所有事实是 Foo 包含 Bar。因此,当您在 Foo 上调用方法时,它会在 Bar 中查找该方法。

如果这是真的,那么在调用 TestTwo::Quux.new.foo 时,我已经将 foo 方法混合到 TestTwo::Bar 中,所以它应该可以工作,对吧?

【问题讨论】:

【参考方案1】:

文档说append_features(由 include 调用)将方法混合到调用者中。所以当TestTwo::Quux 包含TestTwo::Bar 时,不会向TestTwo::Quux 添加任何方法。下一行将方法添加到 TestTwo::Bar,但不添加到 TestTwo::Quux

【讨论】:

这很遗憾,因为在我的真实情况下,第一个包含发生在我的控制之外,我只是想将一些东西混合到任何包含我的目标模块的东西中。嗯,谢谢:)

以上是关于为啥在 Ruby 中包含模块的顺序会有所不同?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby在模型中包含模块的单一方法

为啥以不同的顺序运行我的测试会导致性能截然不同? [复制]

访问模块中包含的 ruby​​ 方法的符号

从单独的文件中包含一个 Ruby 类

MS SQL中包含索引

jQuery mobile 中包含 ajax 时的函数执行顺序