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'