Почему методы установки не используются при инициализации?
Недавно я читал "Практический объектно-ориентированный дизайн в 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." квалификация внутри класса?.