Ruby模块类方法继承

时间:2014-05-14 11:35:59

标签: ruby module

如何在嵌套的模块系列中定义类方法在模块mixin树中向上传播?

请考虑以下事项:

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语言。

亲切的问候

史蒂夫

2 个答案:

答案 0 :(得分:0)

如果您不想手动延长ClassMethods,并且您希望任何人B将其类界面扩展为ClassMethods,那么您可以这样做:

module B
  include A

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

或者您可以将B定义为class并让C继承自{{1}}。我想这一切都取决于你的设计以及你想要达到的目的。

答案 1 :(得分:0)

好的 - 所以我明白了。这是一个轻微的黑客攻击,因为它依赖于模块层次结构,总是使用模块名称ClassMethods来保存任何类方法。

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

 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