0

当我在 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 是否使用快捷方式来更有效地实现这样的事情?

4

3 回答 3

1

从问题的表述方式来看,您可能应该重新考虑课程的设计。然而,Ruby 提供了一种有趣的方式来快速创建带有attr_accessors(不是 reader)的类。这是一个简单的例子:

>> 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 = foosetter)。

如果您真的不想要作者,请将它们设为私有或将它们设为私有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,但是有人想知道您是否真的想要许多构造函数参数,或者您是否只有一个散列参数并将其合并到默认散列中。

于 2012-03-14T20:00:12.080 回答
0

您可以使用引入参数对象重构方法来简化构造函数调用。

于 2012-03-14T20:00:21.003 回答
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

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

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
于 2012-03-14T19:59:38.527 回答