Избегать повторения при определении класса в Ruby? - PullRequest
0 голосов
/ 14 марта 2012

Я часто повторяю свои вещи, когда создаю классы в 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 ]

1 голос
/ 15 марта 2012

Судя по тому, как сформулирован вопрос, вам, вероятно, следует переосмыслить дизайн ваших классов.Тем не менее, 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=]

Конечно, это нормальный класс, и вы можете добавить все методы, которые вы хотите (и использовать геттеры и сеттеры вместо переменных экземпляра, например, var для геттера и self.var = foo для сеттера).

Если вы действительно не хотите авторов, сделайте их личными или 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, но потом возникает вопрос: действительно ли вы хотите использовать множество аргументов конструктора или, может быть, у вас есть только один аргумент хеш-функции и объединить его в хеш-код по умолчанию.

0 голосов
/ 15 марта 2012

Вы можете использовать ввод объекта параметра метод рефакторинга для упрощения вызова конструктора.

0 голосов
/ 14 марта 2012

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
...