Singleton Class / Eigenclass
Собственный класс называется классом-одиночкой, потому что он следует шаблону Singleton. Паттерн Singleton - это простой объектно-ориентированный шаблон программирования, в котором гарантируется наличие только одного экземпляра определенного класса.
В Ruby паттерн Singleton реализуется с помощью модуля, достаточно добавить Include Singleton в определение класса. Этот модуль, по сути, скрывает метод :new. MySingletonObject.new всегда будет выдавать ошибку. Вместо этого он предоставляет метод экземпляра, который всегда будет возвращать один и тот же уникальный экземпляр класса.
require 'singleton'
class NotSingleton
# 'initialize' is called everytime an instance is created
def initialize
puts 'This will be printed many times'
end
end
class MySingleton
include Singleton
# 'initialize' is called ONCE an instance is created
def initialize
puts 'This will be printed once'
end
end
NotSingleton.new # => 'This will be printed many times'
NotSingleton.new # => 'This will be printed many times'
NotSingleton.new # => 'This will be printed many times'
MySingleton.instance # => 'This will be printed once'
MySingleton.instance # Nothing is printed
MySingleton.instance # Nothing is printed
При создании экземпляра класса Ruby создает скрытый класс, по сути, копию исходного класса, которая принадлежит исключительно этому экземпляру. Это и есть собственный класс (Eigenclass). Если вы измените собственный класс первого экземпляра, это никак не повлияет на другой экземпляр.
# This class is NOT a singleton
class ExampleObject
def print_hello
puts 'Hello'
end
end
object1 = ExampleObject.new
object2 = ExampleObject.new
object1.print_hello # => 'Hello'
object2.print_hello # => 'Hello'
def object2.print_hello
puts 'Bonjour'
end
object1.print_hello # => 'Hello'
object2.print_hello # => 'Bonjour'
Поскольку собственный класс может существовать только в одном экземпляре, его иногда называют классом-синглтоном, хотя ExampleObject вовсе не является синглтоном. Только собственные классы его экземпляров являются синглтонами, потому что каждый из них один и уникален.
The class << self notation
Cинтаксис class << object используется для доступа к собственному классу объекта.
class ExampleObject
def print_hello
puts 'Hello'
end
end
object1 = ExampleObject.new
object2 = ExampleObject.new
class << object2
def print_hello
puts 'Aloha'
end
end
object1.print_hello # => 'Hello'
object2.print_hello # => 'Aloha'
Если используются методы класса, фактически используется собственный класс.
class MyModel
# Class Method
def self.print_hello
puts 'Hello'
end
# Instance Method
def print_bonjour
puts 'Bonjour'
end
end
MyModel.print_hello # => 'Hello'
MyModel.new.print_hello # => ERROR
MyModel.print_bonjour # => ERROR
MyModel.new.print_bonjour # => 'Bonjour'