Відповіді:
Запис @age
безпосередньо отримує доступ до змінної екземпляра @age
. Написання self.age
вказує об'єкту відправити собі повідомлення age
, яке зазвичай повертає змінну екземпляра @age
- але може робити будь-яку кількість інших речей залежно від age
способу реалізації в заданому підкласі. Наприклад, у вас може бути клас MiddleAgedSocialite, який завжди повідомляє про свій вік на 10 років молодший, ніж він є насправді. Або, практично, клас PersistentPerson може ліниво читати ці дані з постійного магазину, кешувати всі його стійкі дані в хеші.
Різниця полягає в тому, що вона ізолює використання методу від його реалізації. Якщо реалізація властивості повинна змінитися - скажімо, зберегти дата народження, а потім обчислити вік, виходячи з різниці в часі між датою і датою народження - тоді код залежно від методу не потрібно змінювати. Якщо він використовував властивість безпосередньо, то зміна повинна поширюватися на інші області коду. У цьому сенсі використання властивості безпосередньо крихке, ніж використання наданого класом інтерфейсу.
Будьте попереджені, коли ви успадковуєте клас, з Struct.new
якого є акуратний спосіб генерувати intializer ( Як генерувати ініціалізатор в 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
поруч один з одним.
Я припускаю, що використання дозволяє в майбутньому записати фактичний getter, що може зробити щось складніше, ніж просто повернути змінну екземпляра, і в цьому випадку метод не потребуватиме змін.
Але це навряд чи турбуватиметься абстракція, адже якщо реалізація об'єкта змінилася, розумно змінити інші методи, в якийсь момент просте посилання всередині самого об’єкта цілком розумне.
У будь-якому випадку, абстракція age
властивості все ще не пояснює явного використання цього виду self
, оскільки просто звичайна age
також викликала б доступ.
@age - це, безумовно, мінливий вік примірника
self.age - відноситься до віку властивості екземпляра.