Ответы:
Запись @age
напрямую обращается к переменной экземпляра @age
. Письмо self.age
говорит объекту отправлять себе сообщение age
, которое обычно возвращает переменную экземпляра, @age
но может делать множество других вещей в зависимости от того, как age
метод реализован в данном подклассе. Например, у вас может быть класс MiddleAgedSocialite, который всегда сообщает о своем возрасте на 10 лет моложе, чем на самом деле. Или, на практике, класс PersistentPerson может лениво читать эти данные из постоянного хранилища, кэшировать все свои постоянные данные в хэш.
Разница в том, что он изолирует использование метода от его реализации. Если реализация свойства должна была измениться - скажем, чтобы сохранить дату рождения, а затем вычислить возраст на основе разницы во времени между текущим временем и датой рождения - тогда код, зависящий от метода, менять не нужно. Если бы оно использовало свойство напрямую, то изменение должно было бы распространиться на другие области кода. В этом смысле непосредственное использование свойства более хрупко, чем использование предоставленного ему класса интерфейса.
Будьте осторожны, когда вы унаследуете класс, из Struct.new
которого вы найдете отличный способ создания инициализатора ( Как создать инициализатор в Ruby? )
class Node < Struct.new(:value)
def initialize(value)
@value = value
end
def show()
p @value
p self.value # or `p value`
end
end
n = Node.new(30)
n.show()
вернется
30
nil
Однако при удалении инициализатора он вернется
nil
30
С определением класса
class Node2
attr_accessor :value
def initialize(value)
@value = value
end
def show()
p @value
p self.value
end
end
Вы должны предоставить конструктор.
n2 = Node2.new(30)
n2.show()
вернется
30
30
Первый ответ совершенно верен, но, как относительный новичок, я не сразу понял, что он имел в виду (отправка сообщений самому себе ... ага ...). Я думаю, что короткий пример поможет:
class CrazyAccessors
def bar=(val)
@bar = val - 20 # sets @bar to (input - 20)
end
def bar
@bar
end
def baz=(value)
self.bar = value # goes through `bar=` method, so @bar = (50 - 20)
end
def quux=(value)
@bar = value # sets @bar directly to 50
end
end
obj = CrazyAccessors.new
obj.baz = 50
obj.bar # => 30
obj.quux = 50
obj.bar # => 50
Там нет никакой разницы. Я подозреваю, что это было сделано только для документальной ценности видения self.age
и other_person.age
рядом друг с другом.
Я полагаю, что использование позволяет в будущем написать реальный геттер, что может сделать что-то более сложное, чем просто вернуть переменную экземпляра, и в этом случае метод не нужно будет менять.
Но об этой абстракции вряд ли стоит беспокоиться, в конце концов, если реализация объекта изменилась, разумно изменить другие методы, в какой-то момент простая ссылка в самом объекте совершенно разумна.
В любом случае, абстракция age
свойства все еще не объясняет явного использования self
, поскольку просто age
бы также вызвал метод доступа.
@age - определенно переменная age
self.age - относится к возрасту свойства экземпляра.