Почему я не могу включить ядро в одноэлементный класс экземпляра Object
Хм, вы можете :
obj = Object.new
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
class << obj
include Kernel
end
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
Примечание: очевидно, что include
вставка Kernel
в экземпляр Object
на самом деле не делает ничего, потому что Kernel
уже уже в цепочке предков, имиксины могут появиться только один раз в цепочке предков.Но если вы include
еще один миксин, он будет работать:
obj = Object.new
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
class << obj
include Enumerable
end
obj.singleton_class.ancestors
# => [Enumerable, Object, Kernel, BasicObject]
, но я сделал это
obj = Object.new
obj.puts 'wow'
Я получил неопределенную ошибку
Нет, нет.Это ошибка, которую вы получили:
# NoMethodError: private method `puts' called for #<Object:0xdeadbed>
Она сообщает вам прямо там в ошибке, в чем проблема: Kernel#puts
является частным, а в Ruby частные методы могут быть тольковызывается в результате отправки сообщения без получателя.Например, вот так:
obj.instance_eval do puts 'wow' end
# wow
или просто
obj.send :puts, 'wow' # send cirvumvents access protection
# wow
, поэтому я предположил, что модуль Kernel не включен в синглтон-класс obj [...]
Почему вы предполагали вместо простой проверки?
obj.singleton_class.ancestors.include? Kernel # => true
, поэтому я сделал
obj.instance_eval do
include Kernel
end
, но я снова получил ошибку:
NoMethodError: неопределенный метод `include 'для #
Опять же, сообщение об ошибке уже говорит вам все, что вам нужно знать: Object
не имеет метода include
и не являетсятам один в его цепи предков.include
- это метод класса Module
, но obj
- это Object
, а не Module
.