如何在另外两个已经包含的模块之间混合一个ruby模块?

如何在另外两个已经包含的模块之间混合一个ruby模块?,ruby,module,Ruby,Module,假设存在以下代码: module Foo def test(x) "Foo #{x}" end end module Bar def test(x) "Bar #{x} " + super end end class C include Foo include Bar end puts C.new.test(2) # => "Bar 2 Foo 2" 我无法访问C类代码,也无法访问Foo和Bar模块 我想在Foo和Bar之间包含一个模块,这样:

假设存在以下代码:


module Foo
  def test(x)
    "Foo #{x}"
  end
end

module Bar
  def test(x)
    "Bar #{x} " + super
  end
end

class C
  include Foo
  include Bar
end

puts C.new.test(2)
# => "Bar 2 Foo 2"
我无法访问C类代码,也无法访问Foo和Bar模块

我想在Foo和Bar之间包含一个模块,这样:


module Between
  def test(x)
    "Between " + super
  end
end

puts C.new.test(2)
# => "Bar 2 Between Foo 2"  

这是如何实现的?

您不想这样做,因为这样一来,其中一个混音器在没有另一个混音器的情况下无法工作,那么将其作为混音器就没有意义了。只需为
类C
中的
测试
-函数制作一个包装器即可

module Foo
  def self.test(x)
    "Foo #{x}"
  end
end

module Bar
  def self.test(x)
    "Bar #{x}"
  end
end

class C
  def test(x)
    Bar::test(x) + " " + Foo::test(x)
  end
end

puts C.new.test(2)
# => "Bar 2 Foo 2"
然而,如果您真的希望得到一些奇怪的信息,那么您的代码几乎是正确的

module Foo
  def test(x)
    "Foo #{x}"
  end
end

module Bar
  def test(x)
    "Bar #{x} " + super(x) # <= you where missing the parameter here
  end
end

class C
  include Foo
  include Bar
end

puts C.new.test(2)
# => "Bar 2 Foo 2"
模块Foo
def测试(x)
“Foo#{x}”
结束
结束
模块条
def测试(x)
“Bar{x}”+超级(x)#“Bar 2 Foo 2”
您可以这样做,前提是您有机会在处理C的定义之前运行代码。一旦定义,从super重新发送的顺序是固定的,因此任何第三方库都无法超越它(如果他们的代码先运行,您就不能在它们之间插入),它只能在包含的模块列表前面。编辑:不完全正确,请参见Boris Stitnicky的答案,该答案有效地利用了子列表(而不是C类列表)的前置,以获得与下面相同的结果

所以你可以这样做:

module Foo; end; module Bar; end; module Between; end
class C
  # The first time a module is included it goes to front of #included_modules array
  include Foo
  include Between
  include Bar
end

require 'foobarlib' # or whatever untouchable thing defines C, Foo and Bar

# Define your Between (this bit could be anywhere before it is needed)
module Between
  def test(x)
    "Between " + super
  end
end

puts C.new.test(2)
# => "Bar 2 Between Foo 2"

但是,请注意,在实践中,应该避免这种毫无意义的模块杂耍。

这将是一种邪恶!比我的答案更简单、更灵活,但我仍在试图理解为什么
C.包含的_模块
最终会以
[Bar,Between,Foo,Kernel]
这种方式结束,而不是
[Between,Bar,Foo,Kernel]
。有趣的问题<代码>C。祖先表现良好。感谢您的回答,它工作得非常完美。有趣的是,
C.included_modules
最终是如何结束的,这一点我是不会想到的。谢谢你的解决方案。只要意识到
include
可以重写,并且不会返回false(与require相反)
module Bar; include Between end
class C; include Bar end
puts C.new.test(2)
#=> Bar 2 Between Foo 2