2014-05-14 74 views
0

如何让嵌套的一系列模块中定义的类方法在模块mixin树中传播?Ruby模块类继承方法

考虑以下几点:

module A 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    def foo; end 

    module ClassMethods 
    def bar; end 
    end 
end 

module B 
    include A 
end 

class C 
    include B 
end 

puts "B class methods: #{(B.methods-Module.methods).inspect}" 
puts "B instance methods #{B.instance_methods.inspect}" 
puts "C class methods: #{(C.methods-Class.methods).inspect}" 
puts "C instance methods #{(C.instance_methods-Class.instance_methods).inspect}" 

C类不继承A中所定义的类方法,即使包括B.

B class methods: [:bar] 
B instance methods [:foo] 
C class methods: [] 
C instance methods [:foo] 

是否能保证在该类一种巧妙的方法来自A的方法向上传播到C(所以我可以调用C.bar)?我正在寻找一种很好的通用方法,它不涉及每个继承的模块专门调用和扩展C的方法。

亲切的问候

史蒂夫

回答

0

如果不想手动扩展ClassMethods,你想任何人,包括B有其类的接口由ClassMethods扩展,你可以这样做:

module B 
    include A 

    def self.included(base) 
    base.extend(ClassMethods) 
    end 
end 

或者,您可以将B定义为class并从中继承C。我想这一切都取决于你的设计以及你想达到的目标。

0

好的 - 所以我想通了。这是一个小小的破解,因为它依赖于总是使用模块名称ClassMethods来保存任何类方法的模块层次结构。

但是,下面的工作(在A中) - 它基本上检测基本模块是否定义了ClassMethods。如果是这样,它将A的Classmethods添加到基类ClassMethods中。如果没有,它创建一个ClassMethods模块(克隆A的类方法)

def self.included(base) 
    extend ClassMethods 

    if base.kind_of? Module 
     if base.include? ClassMethods 
     base::ClassMethods.extend(ClassMethods) 
     else 
     base.const_set(:ClassMethods, ClassMethods) 
     base.module_eval('def self.included(klass);klass.extend(ClassMethods.clone);end') 
     end 
    end 
    end