0
在这篇文章里面已经介绍了一种方法 http://tech.tulentsev.com/2012/02/ruby-how-to-override-class-method-with-a-module/,但我还可以分享另外的方法。
能够直接用prepend么?不行。你可以试试下面的例子。虽然说,被prepend的module会放到class的继承链的下方,但实际上,类方法却不受影响。
Posted on
Tuesday, September 04, 2018
by
醉·醉·鱼
and labeled under
ruby
You have a class with a class method. Write a module that, when included, will override that class method.
在这篇文章里面已经介绍了一种方法 http://tech.tulentsev.com/2012/02/ruby-how-to-override-class-method-with-a-module/,但我还可以分享另外的方法。
方法一:用instance_eval。原文中的方法。
方法二:用 class << base ; end
方法三:用prepend。如果你知道extend实际上就是class << base; include ClassMethods end的话,你就很好理解为啥prepend在这里可以起作用了。前两者都是直接修改类方法,而这直接通过修改继承链的方法去覆盖类方法。
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
Post a Comment