我想覆盖来自另一个模块B的模块A的方法,该方法将猴子补丁A.
http://codepad.org/LPMCuszt
module A
def foo; puts 'A' end
end
module B
def foo; puts 'B'; super; end
end
A.module_eval { include B } # why no override ???
class C
include A
end
# must print 'A B', but only prints 'A' :(
C.new.foo
答案 0 :(得分:6)
module A
def foo
puts 'A'
end
end
module B
def foo
puts 'B'
super
end
end
include A # you need to include module A befor you can override method
A.module_eval { include B }
class C
include A
end
C.new.foo # => B A
答案 1 :(得分:2)
包含一个模块将放在上面包含在类层次结构中的模块/类。换句话说,A#foo不是B#foo的超级,而是反过来。
如果你想将一个模块作为一种做多重继承的方法,这是有道理的,include SomeModule
是一种说法,“对待SomeTodule就好像它是我的父类”。
要获得您想要的输出,您需要反转包含,以便B包含A:
module A
def foo; puts 'A' end
end
module B
def foo; puts 'B'; super; end
end
B.module_eval { include A } # Reversing the inclusion
class C
include B # not include A
end
puts C.new.foo
编辑以回应评论:
然后要么在A中包括A和B,而在A:
之后包括B.# A and B as before without including B in A.
class C
include A
include B
end
或在C本身补丁A,不要打扰B.
# A as before, no B.
class C
include A
def foo; puts 'B'; super; end
end
这种方法的唯一方法是,如果C上的方法查找是C - > B - > A并且没有将B包含在C中就无法做到这一点。
答案 2 :(得分:0)
实现此目的的另一种方法是在包含模块A时包含模块B.
module A
def foo
puts "this should never be called!"
"a"
end
end
module B
def foo
"b"
end
end
module A
def self.included(base)
base.class_eval do
include B
end
end
end
class C
include A
end
C.new.foo # "b"
答案 3 :(得分:0)
这也是您问题的一个解决方案。我试图通过模块挂钩 included
来实现。将模块A 包含到 C类中时。 模块A 中定义的包含回调被调用并执行。我们在运行中包含模块B 。所以我们的模块方法 foo 被模块B foo 覆盖,以打印名为超。
module A
def self.included klass
klass.send(:include, B)
end
def foo
puts 'A'
end
end
module B
def foo
super
puts 'B'
end
end
class C
include A
end
C.new.foo #out put A,B