Избегать повторений при определении класса в Ruby?

StackOverflow https://stackoverflow.com//questions/9709075

  •  14-12-2019
  •  | 
  •  

Вопрос

Я обнаруживаю, что часто повторяюсь, когда создаю классы в 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 ярлык для более эффективной реализации чего-то подобного?

Это было полезно?

Решение

Судя по тому, как сформулирован вопрос, вам, вероятно, следует переосмыслить дизайн ваших классов.Однако Ruby предоставляет интересный способ быстрого создания классов с помощью attr_accessorсубъекты (не читатели).Вот простой пример:

>> 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=]

Конечно, это обычный класс, и вы можете добавить все методы, которые хотите (и использовать getters и setters вместо переменных экземпляра, например 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 конечно, но тогда возникает вопрос, действительно ли вам нужно много аргументов конструктора или, возможно, у вас есть только один хэш-аргумент и вы объединяете его в хэш по умолчанию.

Другие советы

Ruby Dynamic и предлагает много с точки зрения самоанализ, поэтому вы можете использовать MetaProgramming (или код записи, который по существу записывает код).В вашем примере есть несколько вещей, которые вы можете сделать, чтобы убрать полкость:

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
.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top