Why can't I include Kernel in the singleton class of an instance of Object
In the top-level :
unbinded_method = method :puts
#=> Object(Kernel)#puts(*arg1)
but I did this
obj = Object.new
obj.puts 'wow'
I got an undefined error
so I assumed the Kernel module didn't include in the singleton class of obj, so I did
obj.instance_eval do
include Kernel
end
but I got error开发者_Go百科 again:
NoMethodError: undefined method `include' for #<Object:0x00000100b14dc8>
Why can't I include Kernel in the singleton class of an instance of Object
Uhm, you can:
obj = Object.new
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
class << obj
include Kernel
end
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
Note: obviously, include
ing Kernel
into an instance of Object
doesn't actually do anything, because Kernel
is already in the ancestor chain, and mixins can only appear once in the ancestor chain. But if you include
another mixin, that will work:
obj = Object.new
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
class << obj
include Enumerable
end
obj.singleton_class.ancestors
# => [Enumerable, Object, Kernel, BasicObject]
but I did this
obj = Object.new obj.puts 'wow'
I got an undefined error
No, you didn't. This is the error you got:
# NoMethodError: private method `puts' called for #<Object:0xdeadbed>
It tells you right there in the error what the problem is: Kernel#puts
is private, and in Ruby, private methods can only be invoked as the result of a receiverless message send. For example like this:
obj.instance_eval do puts 'wow' end
# wow
or just
obj.send :puts, 'wow' # send cirvumvents access protection
# wow
so I assumed the Kernel module didn't include in the singleton class of obj [...]
Why did you assume instead of just check?
obj.singleton_class.ancestors.include? Kernel # => true
so I did
obj.instance_eval do include Kernel end
but I got error again:
NoMethodError: undefined method `include' for #
Again, the error message already tells you everything you need to know: Object
doesn't have an include
method, nor is there one in its ancestor chain. include
is a method of the Module
class, but obj
is an Object
, not a Module
.
精彩评论