Почему методы установки не используются при инициализации?

Недавно я читал "Практический объектно-ориентированный дизайн в Ruby", и я заметил, что одной из лучших практик было использование методов доступа, а не прямое захват @instance_variable. Например:

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    @bar = my_argument
  end

  # bad
  # def lorem_ipsum
  #     @bar * 999
  # end

  # good
  def lorem_ipsum
    bar * 999
  end

end

Имеет смысл держать вещи сухими, и в случае, если мне нужно как-то обработать @bar, прежде чем на самом деле захватить его значение. Однако я заметил, что метод initialize напрямую задает значение переменной экземпляра @bar:

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    @bar = my_argument #<-- why isn't self.bar = my_argument used here?
  end

Есть ли причина для этого? Не следует ли использовать метод setter вместо прямого использования оператора = для установки значения переменной экземпляра?

Ответ 1

Вы правы, было бы гораздо разумнее делать

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    self.bar = my_argument
  end
end

Аргументы различаются в отношении того, следует ли вам уважать инкапсуляцию внутри самого объекта или нет, но если вы в это верите, тогда да, вы должны это сделать.

Ответ 2

Инициализатор УСТАНАВЛИВАЕТ значение при инициализации. Аксессуар позволяет вам получить доступ (чтение/запись) через символ после того, как объект уже создан.

Этот пост может помочь вам понять: Что такое attr_accessor в Ruby?

Ответ 3

Собственно, установщик может использоваться в initialize так же, как и в других методах, но установщик не может использоваться без приемника.

Я думаю, вы можете использовать a_foo.bar= или self.bar=, но не можете использовать bar= без получателя, потому что в более позднем случае bar будет рассматриваться как локальная переменная, а не метод setter:/p >

class Song
  attr_accessor :name
  def initialize(name)
    self.name = name
  end
  def test_setter1(value)
    @name = value
  end
  def test_setter2(value)
    name = value #name is local variable
  end
end

s = Song.new("Mike")
p s
s.test_setter1("John")
p s
s.test_setter2("Rosy")
p s

Это приводит к:

#<Song:0x23a50b8 @name="Mike">
#<Song:0x23a50b8 @name="John">
#<Song:0x23a50b8 @name="John">

Ответ 4

Пока вы можете использовать установщик в инициализации, как показано в ответ @uncutstone, вы не можете использовать его, как вы предложили в комментарии в коде.

Проблема в том, что Ruby интерпретирует:

bar = my_argument

как назначение локальной переменной bar, а не вызов метода bar=.

Это довольно подробно обсуждается в разделе "Почему в настройках Ruby требуется "self." квалификация внутри класса?.