给定一个带有单例方法的模块:
module Foo
class << self
def bar
puts "method bar from Foo"
end
end
end
如何使用其他模块覆盖Foo.bar
?
答案 0 :(得分:3)
此代码
module Foo
class << self
def bar
puts "method bar from Foo"
end
end
end
等于
class << Foo
def bar
puts "method bar from Foo"
end
end
也等于
def Foo.bar
puts "method bar from Foo"
end
因此,您可以调用它在定义Foo
的任何地方重新定义此方法(使用另一个模块,不包括Foo
)。
答案 1 :(得分:1)
我的问题是我忘了透过继承链。我曾是 寻找通过修改继承链来覆盖方法的方法,但是 那是不可能的。
原因是bar
本身定义了Foo
,因此它永远不会查找该方法的继承链。因此,要更改bar
,我必须在Foo
本身更改它。
虽然我可以重新打开Foo,但是这样:
module Foo
def self.bar
puts "new foo method"
end
end
...我更喜欢一种能够包装原始bar
方法的方法,就好像我一样
是子类,可以调用super
。我可以通过设置一个来实现这一目标
旧方法的别名。
module Foo
class << self
def bar
"method bar from Foo"
end
end
end
puts Foo.bar # => "method bar from Foo"
module FooEnhancement
# Add a hook - whenever a class or module calls `extend FooEnhancement`,
# run this code
def self.extended(base)
# In the context of the extending module or class
# (in this case, it will be Foo), do the following
base.class_eval do
# Define this new method
def self.new_bar
"#{old_bar} - now with more fiber!"
end
# Set up aliases.
# We're already in the context of the class, but there's no
# `self.alias`, so we need to call `alias` inside this block
class << self
# We can call the original `bar` method with `old_bar`
alias :old_bar :bar
# If we call `bar`, now we'll get our `new_bar` method
alias :bar :new_bar
end
end
end
end
# This will fire off the self.extended hook in FooEnhancement
Foo.extend FooEnhancement
# Calls the enhanced version of `bar`
puts Foo.bar # => 'method bar from Foo - now with more fiber!'
答案 2 :(得分:0)
您可以执行以下操作:
module Foo
class << self
def bar
puts "method bar from Foo"
end
def baz
puts "method baz from Foo"
end
end
end
module Foo2
def Foo.bar
puts "new version of bar"
end
end
include Foo
Foo.baz #=> method baz from Foo
Foo.bar #=> new version of bar
或者只需重新打开Foo2
,而不是命名Foo
。
module Foo
class << self
def bar
puts "method bar from Foo"
end
def baz
puts "method baz from Foo"
end
end
end
module Foo
class << self
def bar
puts "new version of bar"
end
end
end
include Foo
Foo.baz #=> method baz from Foo
Foo.bar #=> new version of bar