在Ruby中定义类时避免重复?

时间:2012-03-14 19:45:24

标签: ruby ruby-1.9.3

当我在ruby中创建类时,我发现自己重复了很多事情,通常我会得到类似于以下内容的东西:

class Foo
  attr_reader :bar_0,
              :bar_1,
                 .
                 .
                 .
              :bar_n
  def initialize( bar_0 = something,
                  bar_1 = something,
                        .
                        .
                        .
                  bar_n = something)
    @bar_0 = bar_0
    @bar_1 = bar_1
           .
           .
           .
    @bar_n = bar_n
  end
end

ruby​​是否采用了一种快捷方式来更有效地实现这样的东西?

3 个答案:

答案 0 :(得分:1)

从问题的表达方式来看,你应该重新考虑你的课程设计。但是,Ruby提供了一种有趣的方法来快速创建具有attr_accessor s(而不是读者)的类。这是一个简单的例子:

>> class Person < Struct.new(:name, :age) ; end
=> nil
>> p = Person.new
=> #<struct Person name=nil, age=nil>
>> p.age = 23
=> 23
>> p.class
=> Person
>> p.methods.grep(/age/)
=> [:age, :age=]

当然这是一个普通的类,您可以添加所需的所有方法(并使用getter和setter而不是实例变量,例如var用于getter,self.var = foo用于setter)。

如果你真的不想要作家,请将它们设为私有或undef

>> attrs = [:name, :age]
=> [:name, :age]
>> class Person < Struct.new *attrs ; end
=> nil
>> Person.instance_eval { private *attrs.map{|attr| "#{attr}=" }}
=> Person
>> p = Person.new
=> #<struct Person name=nil, age=nil>
>> p.methods.grep(/age/)
=> [:age]

当然,上述所有内容对initialize中的大量任务没有帮助,但是人们想知道你是否真的想要很多构造函数参数,或者你是否只有一个哈希参数并将其合并到默认哈希。

答案 1 :(得分:0)

Ruby是动态的,并且在内省方面提供了很多,因此您可以使用元编程(或编写基本上编写代码的代码)。在您的示例中,您可以执行以下操作来清除详细程度:

class Foo
  # Rather than writing bar_1, bar_2, bar_3, ...
  attr_accessor ((0..9).to_a + ('a'..'n').to_a).map { |x| :"foo_#{x}" }

  # Using mass assignment...
  def initialize(attributes = {})
    attributes.each do |attribute, value|
      respond_to?(:"#{attribute}=") && send(:"#{attribute}=", value)
    end
  end
end

由于质量分配是一种流行且可重复使用的行为,因此将其提取到一个单独的模块并使其成为混合模式是有意义的:

module MassAssignment
  def initialize(attributes = {})
    mass_assign(attributes)
  end

  def mass_assign(attributes)
    attributes.each do |attribute, value|
      respond_to?(:"#{attribute}=") && send(:"#{attribute}=", value)
    end
  end
end

class Foo
  include MassAssignment
end

答案 2 :(得分:0)

您可以使用introduce parameter object重构方法来简化构造函数调用。