Eigenclass (также известный как singleton-класс или метакласс) - это скрытый класс, который Ruby автоматически создает для каждого объекта. Этот класс хранит методы, специфичные для конкретного объекта (так называемые методы-одиночки).
ancestors
obj = Object.new
eigenclass = class << obj; self; end
# Или через метод:
eigenclass = obj.singleton_class
str = "hello"
def str.uppercase
self.upcase
end
# Метод хранится в eigenclass'е строки
str.singleton_methods # => [:uppercase]
Классы в Ruby - тоже объекты, поэтому у них есть eigenclass:
class MyClass; end
class << MyClass
def class_method
"Это метод в eigenclass'е MyClass"
end
end
class A; end
class B < A; end
B.singleton_class.superclass == A.singleton_class # => true
Цепочка поиска для объекта obj
:
obj.singleton_class
)obj.class
)include
)class MyClass
def self.class_method; end
end
MyClass.singleton_methods # => [:class_method]
module M; end
class C
include M # Методы добавляются в экземпляры
extend M # Методы добавляются в eigenclass (становятся методами класса)
end
class C
prepend M # Вставляет модуль перед классом в цепочке наследования
end
require 'singleton'
class Logger
include Singleton
def log(msg)
puts "[#{Time.now}] #{msg}"
end
end
# Logger.new запрещен, используется Logger.instance
class User; end
admin = User.new
def admin.admin?
true
end
regular = User.new
regular.admin? # => NoMethodError
class Class
def attr_accessor_with_history(*attrs)
attrs.each do |attr|
define_method(attr) { instance_variable_get("@#{attr}") }
define_method("#{attr}=") do |val|
@history ||= {}
@history[attr] ||= []
@history[attr] << val
instance_variable_set("@#{attr}", val)
end
define_method("#{attr}_history") { @history[attr] }
end
end
end
singleton_class
вместо class << obj; self; end
для ясностиРезюмируем: eigenclass - это мощный механизм Ruby, лежащий в основе системы методов-одиночек и классовых методов. Понимание eigenclass'ов критически важно для глубокого владения метапрограммированием в Ruby и создания гибких, динамических архитектур. Это концепция, которая отличает Ruby от многих других языков программирования.