方法一:用instance_eval。原文中的方法。
module BooModule
def self.included base
base.instance_eval do
def bar
puts "module"
end
end
end
end
class KlassC
def self.bar
puts 'class'
end
end
KlassC.send(:include, BooModule)
KlassC.bar #=> module
p KlassC.ancestors
方法二:用 class << base ; end
module TooModule
def self.included base
class << base
def bar
puts "module"
end
end
end
end
class KlassD
def self.bar
puts 'class'
end
end
KlassD.send(:include, TooModule)
KlassD.bar #=> module
p KlassD.ancestors
方法三:用prepend。如果你知道extend实际上就是class << base; include ClassMethods end的话,你就很好理解为啥prepend在这里可以起作用了。前两者都是直接修改类方法,而这直接通过修改继承链的方法去覆盖类方法。
module GooModule
def self.included base
class << base
prepend ClassMethods
end
end
module ClassMethods
def bar
puts "module"
end
end
end
class KlassE
def self.bar
puts 'class'
end
end
KlassE.send(:include, GooModule)
KlassE.bar #=> module
p KlassE.ancestors
能够直接用prepend么?不行。你可以试试下面的例子。虽然说,被prepend的module会放到class的继承链的下方,但实际上,类方法却不受影响。
module FooModule
def self.included base
base.extend ClassMethods
end
def self.prepended base
base.extend ClassMethods
end
module ClassMethods
def bar
puts "module"
end
end
end
class KlassA
include FooModule
def self.bar
puts 'class'
end
end
KlassA.bar #=> class
p KlassA.ancestors
class KlassB
prepend FooModule
def self.bar
puts 'class'
end
end
KlassB.bar #=> class
p KlassB.ancestors
转载需保留链接来源:软件玩家 » Ruby如何使用Module覆盖类方法