假设存在以下代码:
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"
这是如何实现的?
答案 0 :(得分:3)
module Bar; include Between end
class C; include Bar end
puts C.new.test(2)
#=> Bar 2 Between Foo 2
但请注意,在实践中,应避免使用这种无意义的模块杂耍。
答案 1 :(得分: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"
答案 2 :(得分:0)
你不想这样做,因为其中一个mixins在没有另一个的情况下不会工作,然后它真的没有把它作为mixin。只需为test
中的class 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"
如果您对某些奇怪的reasson 真的想要这个,那么您的代码几乎是正确的。
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"