2015-02-15 1 views
1

Я вижу это выскакиваю все время в моем кодеКак избежать переменного экземпляра инициализации уродства

class Foo 
    def initialize(foo) 
    @foo = foo 
    end 
    #... 
end 

Это не так уж плохо, но это еще хуже:

class Foo 
    def initialize(foo,baz,bar,a,b,c,d) 
    @foo = foo 
    @baz = baz 
    @bar = bar 
    #etc... 

Вы можете sortof обойти это, сделав что-то вроде

@foo, @baz, @bar = foo, baz, bar 

Но даже это кажется неправильным и раздражает, чтобы печатать. Есть ли лучший способ определить переменные экземпляра в соответствии с аргументами?

Редактировать: Кажется, существует 2 различных решения этой проблемы. См:

+1

http://stackoverflow.com/questions/2680523/ –

ответ

7

Вы можете рассмотреть с помощью Struct:

class Foo < Struct.new(foo,baz,bar,a,b,c,d) 
end 

foo = Foo.new(1,2,3,4,5,6,7) 
foo.bar #=> 2 

Нет необходимости определять дополнительный initialize метод вообще .. .

3
def initialize args 
    @foo, @baz, @bar = *args 
end 
3

Да, это предпочтительный способ инициализации переменных экземпляра в Ruby. Это может раздражать тип, но это хорошо понятый образец. Как всегда в Ruby, использование метапрограммирования для его автоматизации возможно, но сделает ваш код более сложным.

Я также утверждаю, что это, вероятно, хорошая вещь для класса выглядеть уродливым, когда он принимает более двух-трех аргументов. Если ваш класс зависит от шести разных функций, он является сильным кандидатом на рефакторинг.

0

Я думаю, что есть 3 способа сделать инициализации переменных экземпляра короче:

  1. Использование Struct или OpenStruct.
  2. Используйте параллельное назначение рубинов.
  3. Используйте метапрограммирование, чтобы сделать макрос, как this.
0

fattr камень недавно был одобрен на Руби Тапас, чтобы помочь решить эту проблему. Еще одно соображение заключается в том, есть ли слишком много вещей, которые передаются в инициализатор. Может быть, этот класс делает слишком много, и его нужно разбить на более мелкие куски.