Я хочу создать объект, который действует как определенный класс, например Fixnum, но не является экземпляром этого класса или его подклассов.
Существуют различные варианты использования для этого. В случае Fixnum я хочу определить более конкретный целочисленный тип, который по сути является Fixnum, но также реализует некоторую дополнительную логику. Я не могу создать подкласс самого Fixnum, потому что непосредственные типы, такие как Fixnum и Symbol, не могут быть подклассами.
Другой вариант использования - имитация автоматических тестов: иногда вы хотите создать объект, который действует как определенный класс (обычно экземпляр модели), но по техническим причинам не является экземпляром этого точного класса.
Вот как создать определенный целочисленный тип, который делегирует все методы внутреннему сохраненному fixnum:
require 'delegate'
require 'forwardable'
# integer representing a page number
class PageNumber < DelegateClass(Integer)
extend Forwardable
def initialize(value, name)
@name = name
super(value)
end
def inspect
"#{@name} #{to_i}"
end
alias_method :to_i, :__getobj__
def_delegators :to_i, :instance_of?, :kind_of?, :is_a?
end
Этот объект может передавать is_a?
и аналогичные проверки:
page = PageNumber.new(1, "page")
page.is_a? Fixnum #=> true
Но ничего, что я делаю, не может заставить его пройти проверку типа Module # ===
:
# my problem:
Fixnum === page #=> false
Тот факт, что мой объект не прошел эту проверку, очень прискорбен, поскольку ===
метод используется внутри case
операторов:
case page
when Fixnum
# it will never get here
when String
# ...
else
# ...
end
Мой вопрос в том, как создать фиктивный тип, который проходит проверку ===
без дополнения методов ===
во встроенных классах?