Ruby 通过在模块中混合重写类的实例方法
给定一个类a和一个模块B,混合B的实例方法,以便覆盖a的相应实例方法Ruby 通过在模块中混合重写类的实例方法,ruby,module,overriding,mixins,Ruby,Module,Overriding,Mixins,给定一个类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 instanc
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"
将模块M
作为类C
的超类插入。因此,您不能在M
中重写C
的方法,相反:C
的方法重写M
的方法。(从技术上讲,Ruby并没有使M
成为C
的超类,而是创建了一个不可见的Include类⟦M′⟧
的方法表和常量表指向M
的方法表和常量表,并使该类成为超类,但这种区别对于这个特定问题并不重要。)
在Ruby 2.0中,有一种新方法,顾名思义,它将M
前置到C
的祖先,换句话说,使M
成为C
的子类
因此,简而言之:您不能,至少现在还不能。您可以在包含
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
规定您不能显式地交换方法(例如,您不能直接引用“method1”或“method2”),这就是我要找的,但无法找到如何做!谢谢更好的方法可能是使用B类中包含的(基本)回调。使用另一个示例更新了答案,以从
B
中删除A
的方法。好吧,您可以通过一些黑客操作来完成(请参阅Stefan的答案),但很高兴知道Ruby正在添加这个,因为它派上了用场。@JoeV:你问过覆盖,我想这包括不破坏super
@Stefan的回答只是删除了这些方法,没有重写,因此,由于不再存在超类方法,因此无法将功能委托给超类方法。现在我们已经远远超过了2.0,对于那些处在我这个位置的人来说,这应该是一个公认的答案,他们想知道如果将模块M
包含在类D
中会发生什么,该类继承自类C
,答案是模块M
中的方法覆盖C
中的方法,但正如这个答案所指出的,不是D
中的方法