为什么我不能在Object的一个实例的单例类中包含Kernel

时间:2011-07-22 13:19:09

标签: ruby metaprogramming

在顶级:

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 个答案:

答案 0 :(得分:5)

  

为什么我不能在Object

的实例的单例类中包含Kernel

嗯,你可以

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已经在祖先链中,而mixins只能在祖先链中出现一次。但是如果你obj = Object.new obj.singleton_class.ancestors # => [Object, Kernel, BasicObject] class << obj include Enumerable end obj.singleton_class.ancestors # => [Enumerable, Object, Kernel, BasicObject] 另一个 mixin,那将会有效:

obj = Object.new

obj.puts 'wow'
  

但我这样做了

# NoMethodError: private method `puts' called for #<Object:0xdeadbed>
     

我收到了一个未定义的错误

不,你没有。这是你得到的错误:

Kernel#puts

它告诉你就在那里错误是什么问题:obj.instance_eval do puts 'wow' end # wow 是私有的,而在Ruby中,私有方法只能作为无接收消息发送的结果来调用。例如:

obj.send :puts, 'wow' # send cirvumvents access protection
# wow

或只是

obj.singleton_class.ancestors.include? Kernel # => true
  

所以我假设内核模块没有包含在obj [...]

的单例类中

你为什么假设而不仅仅是检查?

obj.instance_eval do
  include Kernel
end
  

所以我做了

Object
     

但我又错了:

     

NoMethodError:未定义的方法`include'for#

同样,错误消息已经告诉您需要知道的所有内容:include没有include方法,其祖先链中也没有。{1}}。 Moduleobj类的一种方法,但ObjectModule,而不是{{1}}。