开发者

Why can't I include Kernel in the singleton class of an instance of Object

开发者 https://www.devze.com 2023-03-22 01:24 出处:网络
In the top-level : unbinded_method = method :puts #=> Object(Kernel)#puts(*arg1) but I did this obj = Object.new

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, includeing 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号