mko*_*mko 3 ruby metaprogramming
在顶级:
unbinded_method = method :puts
#=> Object(Kernel)#puts(*arg1)
Run Code Online (Sandbox Code Playgroud)
但我这样做了
obj = Object.new
obj.puts 'wow'
Run Code Online (Sandbox Code Playgroud)
我收到了一个未定义的错误
所以我假设内核模块没有包含在obj的单例类中,所以我做到了
obj.instance_eval do
include Kernel
end
Run Code Online (Sandbox Code Playgroud)
但我又得到了错误:
NoMethodError: undefined method `include' for #<Object:0x00000100b14dc8>
Run Code Online (Sandbox Code Playgroud)
为什么我不能在Object的一个实例的单例类中包含Kernel
嗯,你可以:
obj = Object.new
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
class << obj
include Kernel
end
obj.singleton_class.ancestors
# => [Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)
注:很明显,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]
Run Code Online (Sandbox Code Playgroud)
但我这样做了
Run Code Online (Sandbox Code Playgroud)obj = Object.new obj.puts 'wow'
我收到了一个未定义的错误
不,你没有.这是你得到的错误:
# NoMethodError: private method `puts' called for #<Object:0xdeadbed>
Run Code Online (Sandbox Code Playgroud)
它会告诉你那里的错误是什么问题:Kernel#puts
是私有的,而在Ruby中,私有方法只能被调用为receiverless消息发送的结果.例如这样:
obj.instance_eval do puts 'wow' end
# wow
Run Code Online (Sandbox Code Playgroud)
要不就
obj.send :puts, 'wow' # send cirvumvents access protection
# wow
Run Code Online (Sandbox Code Playgroud)
所以我假设内核模块没有包含在obj的单例类中[...]
你为什么假设而不仅仅是检查?
obj.singleton_class.ancestors.include? Kernel # => true
Run Code Online (Sandbox Code Playgroud)
所以我做了
Run Code Online (Sandbox Code Playgroud)obj.instance_eval do include Kernel end
但我又得到了错误:
NoMethodError:未定义的方法`include'for#
同样,错误消息已经告诉您需要知道的所有内容:Object
没有include
方法,祖先链中也没有方法.include
是一个Module
类的方法,但是obj
是一个Object
,而不是一个Module
.
归档时间: |
|
查看次数: |
252 次 |
最近记录: |