Почему я не могу включить ядро ​​в одноэлементный класс экземпляра Object - PullRequest
3 голосов
/ 22 июля 2011

На верхнем уровне:

unbinded_method = method :puts

#=> Object(Kernel)#puts(*arg1)

но я сделал это

obj = Object.new

obj.puts 'wow'

Я получил неопределенную ошибку

, поэтому я предположил, что модуль ядра не сделал 'Я включил в синглтон-класс obj, поэтому я сделал

obj.instance_eval do

include Kernel

end

, но снова получил ошибку:

NoMethodError: undefined method `include' for #<Object:0x00000100b14dc8>

1 Ответ

5 голосов
/ 22 июля 2011

Почему я не могу включить ядро ​​в одноэлементный класс экземпляра 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.

...