Модули не могут быть инстанцированы, поэтому это естественный способ:
module Utility
def self.helper_method
"Я могу быть вызван без создания экземпляра"
end
end
Utility.helper_method # => Работает
Utility.new # => NoMethodError: undefined method `new' for Utility:Module
Делаем метод new
недоступным извне класса:
class SingletonLike
private_class_method :new
def self.instance
@instance ||= new
end
end
SingletonLike.instance # => #<SingletonLike:0x00007f8e7a0b4a20>
SingletonLike.new # => NoMethodError: private method `new' called for SingletonLike:Class
Явное предотвращение создания экземпляра:
class AbstractClass
def initialize
raise "Это абстрактный класс, создание экземпляров запрещено"
end
end
AbstractClass.new # => RuntimeError: Это абстрактный класс...
Создание класса без метода new
:
class NoInstanceClass < BasicObject
# Не определяем метод new
end
NoInstanceClass.new # => NoMethodError: undefined method `new' for NoInstanceClass:Class
class MathUtils
def self.square(x)
x * x
end
private_class_method :new
end
MathUtils.square(5) # => 25
MathUtils.new # => Ошибка
require 'singleton'
class AppConfig
include Singleton
def settings
@settings ||= load_config
end
private
def load_config
# Загрузка конфигурации
end
end
config = AppConfig.instance # Всегда один и тот же объект
AppConfig.new # => NoMethodError: private method `new' called for AppConfig:Class
class Product
def self.create(type)
case type
when :book then Book.new
when :movie then Movie.new
else raise "Неизвестный тип продукта"
end
end
private_class_method :new
end
class Book < Product; end
class Movie < Product; end
Product.create(:book) # => #<Book:0x00007f8e7a0b4a20>
Product.new # => Ошибка
class Proxy
def self.new(*args)
RealObject.new(*args)
end
end
class RealObject; end
Proxy.new # => #<RealObject:0x00007f8e7a0b4a20>
class Final
def self.inherited(subclass)
raise "Наследование от Final запрещено"
end
private_class_method :new
end
class Attempt < Final # => RuntimeError: Наследование от Final запрещено
end
obj = MyClass.allocate # Создает объект без вызова initialize
Резюмируем: в Ruby есть несколько эффективных способов предотвратить создание экземпляров объекта - от простого использования модулей до более сложных паттернов вроде Singleton. Выбор подхода зависит от конкретной задачи: нужны ли классовые методы, требуется ли контролируемое создание объектов или полный запрет инстанцирования. Понимание этих техник важно для создания правильной архитектуры в Ruby-приложениях.