如何在另外两个已经包含的模块之间混合一个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