У 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