通过混合模块来覆盖类的实例方法
给定A类和模块B,混合B的实例方法,使其覆盖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"
在包括B
之前,您可以从A
删除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
或者从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
Module#include
#include将模块M
作为C
类的超类插入。 所以,你不能在M
覆盖C
的方法,而是相反的方式: C
的方法覆盖了M
的方法。 (从技术上讲,Ruby不会使M
成为C
的超类,而是创建一个不可见的Include类 ⟦M′⟧
其方法表和常量表指向M
的方法表和常量表,并使该类成为超类,但这种区别对于这个特殊问题并不重要。)
在Ruby 2.0中,有一个新的方法, Module#prepend
,正如其名称所暗示的那样, 将 M
到C
的祖先,换句话说,使M
成为C
的子类 。
所以,简而言之:你不能,至少还没有。