Ruby: более короткий способ определения переменных экземпляра

Я ищу более короткий способ определения переменных экземпляра внутри метода initialize:

class MyClass
  attr_accessor :foo, :bar, :baz, :qux
  # Typing same stuff all the time is boring
  def initialize(foo, bar, baz, qux)
    @foo, @bar, @baz, @qux = foo, bar, baz, qux
  end
end

Есть ли в Ruby какая-нибудь встроенная функция, позволяющая избежать такой обезьяньей работы?

# e. g.
class MyClass
  attr_accessor :foo, :bar, :baz, :qux
  # Typing same stuff all the time is boring
  def initialize(foo, bar, baz, qux)
    # Leveraging built-in language feature
    # instance variables are defined automatically
  end
end

person DreamWalker    schedule 04.03.2016    source источник


Ответы (1)


Встречайте Struct, инструмент, созданный именно для этого!

MyClass = Struct.new(:foo, :bar, :baz, :qux) do
  # Define your other methods here. 
  # Initializer/accessors will be generated for you.
end

mc = MyClass.new(1)
mc.foo # => 1
mc.bar # => nil

Я часто вижу, как люди используют Struct следующим образом:

class MyStruct < Struct.new(:foo, :bar, :baz, :qux)
end

Но это приводит к одному дополнительному неиспользуемому объекту класса. Зачем создавать мусор, если он вам не нужен?

person Sergio Tulentsev    schedule 04.03.2016
comment
В чем преимущество определения класса таким образом? - person Ganesh Kunwar; 04.03.2016
comment
Я имею в виду способ, который вы используете в своем ответе. - person Ganesh Kunwar; 04.03.2016
comment
В моем ответе есть два пути. - person Sergio Tulentsev; 04.03.2016
comment
Первый способ в вашем ответе. - person Ganesh Kunwar; 04.03.2016
comment
@GaneshKunwar: как насчет чтения связанных документов? А остальной ответ? - person Sergio Tulentsev; 04.03.2016
comment
@SergioTulentsev, что, если мне не нужны считыватели атрибутов, а просто нужны переменные экземпляра для определения? - person DreamWalker; 04.03.2016
comment
@DreamWalker: но вам нужны средства доступа, как показано в ваших фрагментах в вопросе. Если в другом случае вы этого не сделаете, вы можете использовать трюк метапрограммирования, аналогичный тому, что был в ответе Лукаса. По моему опыту, если у вас ивар, то для него нужен как минимум ридер. Работать с голыми иварами — плохая практика. - person Sergio Tulentsev; 04.03.2016
comment
Ваш ответ был бы лучше без примера подкласса :-) - person Stefan; 04.03.2016
comment
@Stefan: это распространенное неправильное использование, поэтому я решил предупредить, чтобы этого не делали :) - person Sergio Tulentsev; 04.03.2016