2012-12-19 146 views
4

我有一个模块Top,它有模块AB。在他们每个人中,我想要使用模块C的类方法。为此,我必须为每个模块AB包含C。是否可以在Top中包含C以便其所有子模块都可以访问其类方法?如何自动将模块包含在嵌套子模块中

例子:

# 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!" 
+1

显示结构,这个问题会更容易理解。 –

+0

您可以从'Z'继承'A'和'B',并将'C'包含到'Z'。 –

回答

2

那么实际上它是可以
OP更新的代码,所以这是我的实现:代码

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" 
+0

谢谢,太好了! – p0deje

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!