在Ruby中,我可以这样做:
module Foo
end
class Bar
include Foo
end
module Foo
def do_something_instancey
puts "I'm an instance!"
end
end
然后,如果我实例化一个Bar
对象,我可以在其上调用do_something_instancey
:
b = Bar.new
b.do_something_instancey
但是,如果我这样做......
module Foo
def self.included(base)
def base.do_something_classy do
puts "I'm a class!"
end
end
end
我的理解是,因为我在{/ 1}} 中包含Foo
之前定义了该类方法,所以我无法调用Bar
,因为它从未被“附加”到Bar.do_something_classy
。
我意识到可能稍微不准确/不是真正合适的术语。无论如何,在上面的示例中,是否有一种方法可以在已经包含模块后将Bar
的类方法附加到Bar
?
答案 0 :(得分:2)
以下是类和实例方法的示例:
module Foo
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
end
end
class Bar
include Foo
end
module Foo
def do_something_instancey
puts "I'm an instance!"
end
module ClassMethods
def do_something_classy
puts "I'm a class!"
end
end
end
b = Bar.new
b.do_something_instancey
# => I'm an instance!
Bar.do_something_classy
# => I'm a class!
要为已经包含特定模块的每个类添加类方法,您可以遍历Ruby的ObjectSpace
:
ObjectSpace.each_object(Class) do |klass|
if klass.include? Foo
klass.define_singleton_method(:do_something_classy) do
puts "I'm a class!"
end
end
end
答案 1 :(得分:1)
retroactive_module_inclusion gem的描述:
这个宝石绕过"动态模块包括" (又名"加倍 包含")问题,这是M.module_eval {包括N. }不会使模块N的方法可用于模块和 事先包含模块M的类,仅限于那些类 之后包括它。这种行为伤害最少 原则,特别是因为如果K是一个类,那么K.class_eval { 包含M} 确实使所有类的M都可用 以前继承了它。