我有一个模块Top
,其中包含模块A
和B
。在每个中,我想使用模块C
的类方法。为此,我必须为每个模块C
和A
添加B
。是否可以在C
中包含Top
,以便所有子模块都可以访问其类方法?
示例:
# I'll extend module C in example to make it shorter
module C
def foo; puts 'Foo!' end
end
module Top
extend C
module A end
module B end
end
# That's how it works now
Top.foo
#=> "Foo!"
Top::A.foo
#=> NoMethodError: undefined method `foo' for Top::A:Module
Top::B.foo
#=> NoMethodError: undefined method `foo' for Top::B:Module
# That's how I want it to work
Top.foo
#=> "Foo!"
Top::A.foo
#=> "Foo!"
Top::B.foo
#=> "Foo!"
答案 0 :(得分:2)
class Module
def submodules
constants.collect {|const_name| const_get(const_name)}.select {|const| const.class == Module}
end
end
module C
# this gets called when the module extends another class or module
# luckily it does _not_ get called when we extend via :send
def self.extended(base)
# collect all submodules and extend them with self
base.submodules.each{|m| m.send :extend, self }
end
def c1
puts "c1"
end
end
module Top
module A;end
module B;end
# extend needs to go at the end - otherwise Top doesnt know about its submodules
extend C
end
Top.c1 # => "c1"
Top::A.c1 # => "c1"
Top::B.c1 # => "c1"
答案 1 :(得分:0)
没有内置方式。你必须实现它:
class Module
def extend_each_module m
constants.each do |sym|
const_get(sym).instance_eval{extend(m) if kind_of?(Module)}
end
end
end
module C
def foo
puts "Foo!"
end
end
module Top
module A; end
module B; end
extend C
extend_each_module C
end
Top.foo
# => Foo!
Top::A.foo
# => Foo!
Top::B.foo
# => Foo!