У Ruby
attr_accessor є макросом (або методом) для автоматичного створення геттера (методу доступу до значення) та сеттера (методу встановлення значення) для інстансних змінних (instance variables) в класі.
Наприклад:
class Cat
end
cat = Cat.new
cat.name # => no method error
Ми не маємо методу
name у класі
Cat. Вочевидь ми отримуємо no method error.
Спробуємо додати геттер:
class Cat
def name
@name # повертає змінну екземпляра @name
end
end
cat = Cat.new
cat.name # => nil
Здається, що щось пішло не так. Але все правильно. Геттер cat.name повертає nil. Вже немає помилки 'no method error', тобто метод існує, та повертає змінну @name екземпляра Cat. Але ця змінна пуста. nil - це очікуємий результат.
У Ruby
геттер є методом, який дозволяє отримати значення інстансної змінної (instance variable) в класі. Геттери називаються так, оскільки вони дозволяють "отримувати" (
get) значення змінної.
У Ruby геттери зазвичай використовуються для забезпечення доступу до значень змінних ззовні класу, оскільки змінні зазвичай є приватними (private) і недоступними безпосередньо. Геттери дозволяють забезпечити контрольований доступ до цих значень.
Cпроба використати сеттер видає помилку no method error:
cat.name = 'Ruby'# => no method error
Це теж очікуємий результат. Ми не маємо сеттер методу для name.
У Ruby сеттер є методом, який дозволяє встановити значення інстансної змінної (instance variable) в класі. Сеттери називаються так, оскільки вони дозволяють "встановлювати" (
set) (або змінювати існуючі) значення змінної.
У Ruby сеттери використовуються для контрольованого змінювання значень змінних ззовні класу.
class Cat
def name
@name # повертає змінну екземпляра @name
end
def name=(str)
@name = str
end
end
Cтворимо екземпляр Cat та викличемо метод name (геттер):
cat = Cat.new
cat.name # => nil
Тут все правильно. Наш екземпляр наразі пустий. Треба передати значення за допомогою нашого нового методу (сеттер).
cat.name = 'Ruby'
Ми не бачимо ніякої помилки. Тож спробуємо за допомого гетер методу витягнути значення:
cat.name # => Ruby
Все працює. Але уявіть, що у вашого класу не тільки name, а десятки різних атрібутів (вік, колір та інше). Кожного разу писати геттер та сеттер методи не дуже зручно.
Тож в Ruby є такі собі скорочення (attr_reader та attr_writer):
class Cat
attr_reader :name
attr_writer :name
end
:name - назва атрібуту, для якого створюється метод.
attr_reader - це скорочення для геттер методу:
def name
@name # повертає змінну екземпляра @name
end
attr_writer - це скорочення для сеттер методу:
def name=(str)
@name = str
end
Але коли нам потрібні обидва методи - сеттер та геттер, attr_reader та attr_writer треба дублювати їх для кожного атрібуту:
class Cat
attr_reader :name
attr_writer :name
attr_reader :color
attr_writer :color
end
Це локанічніше ніж писати методи повністю, але Ruby дає змогу скоротити і цей код. тут нам потрібен
attr_accessor.
class Cat
attr_accessor :name
attr_accessor :color
end
class Cat
attr_reader :name
attr_writer :name
attr_reader :color
attr_writer :color
end
Використання
attr_accessor, attr_reader та attr_writer спрощує створення методів доступу до змінних у класах, і це особливо зручно, коли вам потрібно лише просто отримати або встановити значення змінної, без додаткової логіки.
Ruby дозволяє скоротити вже те, що здається ти вже скоротив. Ось варіант скороченного запису атрибутів через кому:
attr_reader :name, :color