问题
Given a class A and a module B, mixin the instance methods of B so that it overrides the correspnding instance methods of A.
module B
def method1
"B\#method1"
end
def method2
"B\#method2"
end
end
class A
def method1
"A\#method1"
end
def method2
"A\#method2"
end
# include B does not override instance methods!
# (module gets mixed into the superclass)
end
puts A.new.method1 # want it to print out "B#method1"
puts A.new.method2 # want it to print out "B#method2"
回答1:
You could remove each of B
's methods from A
before including B
.
class A
def method1
"A\#method1"
end
def method2
"A\#method2"
end
B.instance_methods(false).each { |method|
remove_method(method) if instance_methods(false).include?(method)
}
include B
end
Or from within B
:
module B
def method1
"B\#method1"
end
def method2
"B\#method2"
end
def self.append_features(mod)
instance_methods(false).each { |method|
mod.send(:remove_method, method) if mod.instance_methods(false).include?(method)
}
super
end
end
回答2:
Module#include inserts the module M
as a superclass of the class C
. So, you can't override C
's methods in M
, rather it's the other way around: C
's methods override M
's methods. (Technically speaking, Ruby doesn't make M
a superclass of C
, rather it creates an invisible Include Class ⟦M′⟧
whose method table and constant table point to M
's method table and constant table, and makes that class the superclass, but this distinction is not important for this particular question.)
In Ruby 2.0, there is a new method, Module#prepend which, just as the name implies, prepends M
to C
's ancestors, in other words, makes M
a subclass of C
.
So, in short: you can't, at least not yet.
来源:https://stackoverflow.com/questions/12057940/overriding-instance-methods-of-a-class-by-mixing-in-a-module