Термін "eigenclass" у Ruby є цікавим і дещо унікальним аспектом її об’єктної моделі. Він тісно пов'язаний з гнучкістю Ruby у метапрограмуванні. Давайте розглянемо його крок за кроком, щоб ви могли зрозуміти його детально.
1. Що таке eigenclass?
Eigenclass (також відома як сінглтон-клас) — це спеціальний, прихований клас, який асоційований з об'єктом. Коли ви визначаєте метод для конкретного об'єкта (замість всього класу), Ruby створює eigenclass для зберігання цього методу.
Ключові моменти:
- Кожен об'єкт у Ruby має свій власний eigenclass.
- Eigenclass зберігає методи, які є специфічними для цього об'єкта.
- Методи в eigenclass мають вищий пріоритет над методами, визначеними в звичайному класі об'єкта.
2. Навіщо нам потрібні eigenclasses?
Eigenclasses дозволяють використовувати сінглтон-методи, які належать одному об'єкту, а не всім екземплярам класу.
Приклад:
str = "hello"
def str.shout
self.upcase + "!!!"
end
puts str.shout # "HELLO!!!"
Що відбувається насправді:
- Ruby створює eigenclass для
str
(якщо він ще не існує). - Метод
shout
додається до eigenclass. - Коли ви викликаєте
str.shout
, Ruby спочатку шукає в eigenclass, знаходитьshout
і виконує його.
3. Як доступитися до eigenclass?
Ви можете отримати доступ до eigenclass об'єкта, використовуючи метод singleton_class
.
str = "hello"
puts str.singleton_class # => #>
# Переглянути методи eigenclass
puts str.singleton_class.instance_methods(false) # [:shout]
4. Як eigenclasses вписуються в ланцюг пошуку методів?
Коли Ruby шукає метод, він перевіряє їх у такому порядку:
- Eigenclass об'єкта.
- Клас об'єкта.
- Модулі, включені в клас.
- Батьківські класи та їхні eigenclasses/модулі, вгору по ланцюгу наслідування.
Це означає, що методи в eigenclass мають вищий пріоритет, ніж методи в звичайному класі або модулях.
Приклад:
class Person
def greet
"Hello!"
end
end
john = Person.new
def john.greet
"Hi!"
end
puts john.greet # "Hi!" (з eigenclass)
5. Eigenclasses для класів (Metaclasses)
Самі класи є об'єктами в Ruby, що означає, що вони також мають свої eigenclasses.
Приклад:
class Dog
end
def Dog.speak
"Woof!"
end
puts Dog.speak # "Woof!"
Що відбувається:
Dog
— це об'єкт класуClass
.- Ruby створює eigenclass для
Dog
. - Метод
speak
додається до eigenclass дляDog
.
Візуалізація ієрархії:
Dog (об'єкт класу Class)
└── Eigenclass для Dog
└── Class (батьківський клас для Dog)
└── Eigenclass для Class
└── Module
6. Явне відкриття eigenclass
Ви можете явно відкрити eigenclass об'єкта, використовуючи синтаксис class << object
:
Приклад:
class Person
end
person = Person.new
class << person
def greet
"Hello from the eigenclass!"
end
end
puts person.greet # "Hello from the eigenclass!"
Тут:
class << person
відкриває eigenclass дляperson
, дозволяючи визначити методи безпосередньо для нього.
7. Практичні випадки використання eigenclasses
Сінглтон-методи:
Використовуються для визначення поведінки, специфічної для одного об'єкта.
logger = Logger.new(STDOUT)
def logger.debug_mode
self.level = Logger::DEBUG
end
logger.debug_mode
Методи класу:
Методи класу зберігаються в eigenclass самого класу.
class Animal
def self.kingdom
"Animalia"
end
end
puts Animal.kingdom # "Animalia"
Тут self.kingdom
зберігається в eigenclass для Animal
.
Метапрограмування:
Використовується для складних технік метапрограмування, коли ви динамічно додаєте методи або поведінку.
Інспекція та відлагодження eigenclasses
Ви можете інспектувати та відлагоджувати eigenclasses за допомогою:
singleton_class
singleton_methods
methods
таinstance_methods
Приклад:
obj = "Ruby"
def obj.unique_method
"I'm unique!"
end
puts obj.singleton_methods # [:unique_method]
puts obj.singleton_class # #>
puts obj.singleton_class.ancestors
Підсумок
- Eigenclasses є важливою частиною об'єктної моделі Ruby, що дозволяє використовувати сінглтон-методи та поведінку, специфічну для класу.
- Вони автоматично створюються, коли ви визначаєте метод для окремого об'єкта.
- Ви можете явно доступитися або змінювати їх за допомогою
singleton_class
абоclass << object
. - Вони є основою для метапрограмування та розуміння ланцюга пошуку методів.
Перекладено з: Eigenclass in ruby