4

假设存在以下代码:


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"  

这是如何实现的?

4

3 回答 3

3
module Bar; include Between end
class C; include Bar end
puts C.new.test(2)
#=> Bar 2 Between Foo 2

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

于 2013-04-27T18:10:50.080 回答
2

可以这样做,只要你有机会在处理 C 的定义之前运行你的代码。一旦定义,从 super 重新发送的顺序是固定的,所以任何第三方库都不能覆盖它(不超过你如果他们的代码首先运行,则可以插入Between),它只能添加到包含模块的列表中。编辑:不完全正确,请参阅 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"
于 2013-04-27T16:00:16.730 回答
0

你不想那样做,因为没有另一个 mixin 将无法工作,然后将它作为 mixin 真的没有任何意义。只需testclass 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"
于 2013-04-27T14:56:07.513 回答