在ruby模块中添加类特定功能

时间:2012-01-19 07:49:06

标签: ruby

可能我没有很好地解释这个概念,但我希望将类方法添加到一系列ruby类中,以使它们能够保存类特定的信息,然后由类的各个实例方法调用。

我可以让它发挥作用,但它有点难看。任何人都可以,因为它需要2个模块,一个包含,另一个扩展(参见下面的示例代码)。

有人能想到更优雅的方式来实现这个功能吗?

由于

史蒂夫

此模块已扩展为提供类方法,但为

中包含的每个类添加实例成员
module My1
   def my_methods (*sym_array)
     @my_methods=sym_array
   end

   def method_list
      @my_methods
   end
end

包含此模块以提供实例方法

module My2
   def foo
      self.class.method_list.each { |m| self.send m }
   end
end

现在使用模块 - 丑陋必须使用include和extend语句,以允许我将一组符号传递给一个类方法,然后在一个类方法中实现 实例

class Foo
   extend My1
   include My2

   my_methods :baz

   def baz
      puts "Baz!"
   end
end

class Bar
   extend My1
   include My2

   my_methods :frodo

   def frodo
      puts "Frodo!"
   end

end

class Wibble < Bar
   extend My1
   include My2

   my_methods :wobble

  def wobble
     puts "Wobble!"
  end
end

这是必需的输出 - 请注意,每个类都有自己的实例@my_methods,因此派生类Wibble&lt;的行为是不同的。杆

f=Foo.new
b=Bar.new
w=Wibble.new

f.foo #=> "Bar!"
b.foo #=> "Frodo!"
w.foo #=> "Wobble!"

2 个答案:

答案 0 :(得分:3)

当包含模块时,会调用一个钩子。您可以使用它来进行所需的扩展。

module M1
  def self.included(base)
    base.extend(M2)
  end
end

人们经常称第二个模块为M1::ClassMethods。如果您使用rails,ActiveSupport::Concern将封装此模式

答案 1 :(得分:1)

我建议使用模块中的钩子:

module MyModule
  def self.included(klass)
    klass.extend ClassMethods
  end

  def foo
    self.class.method_list.each{ |m| self.send m }
  end

  module ClassMethods
    attr_reader :method_list

    def my_methods(*sym_array)
      @method_list = sym_array
    end
  end
end

因此,只要您希望给定类的功能,就可以简化调用仅包含模块。

class Foo
  include MyModule

   my_methods :baz

   def baz
      puts "Baz!"
   end
end