Я пишу модуль с методом foo
, который вызывает метод класса bar
в классе получателя. Мой текущий подход заключается в использовании self.class.bar
, который прекрасно работает, если метод класса не определен в классе экземпляра, а не «реальный» один:Проверьте, имеет ли объект одноэлементный класс
module M
def foo
self.class.bar
end
end
obj = Object.new
class << obj
include M
def self.bar
42
end
end
obj.foo # => NoMethodError: undefined method `bar' for Object:Class
Это имеет смысл, потому что obj.class
не возвращает одноэлементных классов. Я мог использовать obj.singleton_class
вместо этого, и все будет работать бесперебойно:
module M
def foo
self.singleton_class.bar
end
end
obj = Object.new
class << obj
include M
def self.bar
42
end
end
obj.foo # => 42
только если метод определен на одноплодный класс по той же причине, что и выше. Хуже того, он создает новый одноэлементный класс для каждого получателя, чего я хочу избежать, поскольку это может быть довольно много объектов. Поэтому вместо этого я хочу каким-то образом получить одноэлементный класс объекта тогда и только тогда, когда уже определен, то есть что-то типа obj.has_singleton_class ? obj.singleton_class : obj.class
. Однако я не мог найти способ выполнить эту проверку.
Этот ответ нуждался в обновлении, так как 'Fixnum' устарел в Ruby 2.4. См. [Этот ответ] (http://stackoverflow.com/a/21411269/513951) by @ JörgWMittag;) –