我知道,我可以用这种方式覆盖模块中的类方法
class Foo
class << self
def some_static_method
puts 'some_static_method'
end
end
end
module BAR
class << Foo
def some_static_method
puts 'another_static_method'
end
end
end
class Foo
include BAR
end
Foo.some_static_method # => 'another_static_method'
是否可以使用实例方法?
答案 0 :(得分:2)
您可以执行以下操作:
class Foo
def self.some_static_method; puts "Hello from Foo" end
end
module Bar
def self.included(base)
base.instance_eval do
def some_static_method; puts "Hello from Bar" end
end
end
end
class Foo
include Bar
end
Foo.some_static_method
这应该有效
<强>更新强>
要覆盖实例方法,请使用:
class Foo
def some_instance_method; puts "Hello from Foo" end
end
module Bar
def self.included(base)
base.class_eval do
def some_instance_method; puts "Hello from Bar" end
end
end
end
class Foo
include Bar
end
Foo.new.some_instance_method
答案 1 :(得分:1)
您的问题实际上与方法覆盖无关。它是关于在模块体中的class ...
构造中引用的类。
当你这样做时
module Bar
class << Foo
p self
end
end
# => #<Class:Foo>
<< Foo
指向主环境中Foo
的单例类,因为class << Foo
无法直接定义尚未定义的类Foo
的单例类提前。因此,它会查找已定义的Foo
,并且可以在主环境中找到此类。
当你这样做时
module Bar
class Foo
p self
end
end
# => Bar::Foo
创建了一个新类Bar::Foo
; Foo
指向新创建的此Bar::Foo
,并且未指向主环境中的Foo
。为了指向它,您必须使用::
明确指定。
module Bar
class ::Foo
p self
end
end
# => Foo
答案 2 :(得分:1)
如果您使用的是Ruby&gt; 2.0.0然后您可以使用的是Module#prepend
。代替include
,您可以prepend
一个模块,并且所有模块的方法都覆盖任何具有相同名称的现有类实例方法。您可以看到一个简单的示例here。
在Ruby 2之前,Rails引入了类似的hack:#alias_method_chain
Here对两种方法进行了很好的比较。