ruby – 通过BasicObject透明度的委托人
上下文:我试图在
Ruby中设置一个Decorator模式.由于Decorator应该将所有未知方法委托给底层对象,因此我使用了Delegator类.
我本可以使用SimpleDelegator,但我想完全理解我在做什么. 所以我提出的基本代码是: class Decorator < Delegator def initialize(component) super @component = component end def __setobj__(o); @component = o end def __getobj__; @component end def send(s,*a); __send__(s,*a) end end 这与SimpleDelegator的实现完全相同.似乎很好. 但我不想要的是处理Decorator的代码知道它正在操纵一个Decorator.我想要完全透明. 此时Decorator.new(Object.new).class返回了Decorator 所以我修改了一下并想出了这个: class Decorator < Delegator undef_method :== undef_method :class undef_method :instance_of? # Stores the decorated object def initialize(component) super @component = component end def __setobj__(o); @component = o end def __getobj__; @component end def send(s,*a) end end 这样,我可以安全地使用class或instance_of?在我的装饰对象上,它将通过method_missing(由Delegator实现)将方法发送到底层对象. 问题是:我不明白为什么我必须undef:class和:instance_of?.我可以看到BasicObject定义:==所以我不得不取消它,但那两个呢? 那两种方法来自哪里?如果它们根本没有实现,为什么我需要取消它们? 谢谢. 解决方法
您可以通过检查方法获得提示:
Decorator.instance_method(:class) # => #<UnboundMethod: Decorator(#<Module:0x00000102137498>)#class> 方法的所有者是Decorator,但实际上是在#< Module:0x00000102137498>中定义的.所以有一个匿名模块来定义它.有意思……让我们来看看: Decorator.ancestors # => [Decorator,Delegator,#<Module:0x00000102137498>,BasicObject] 在Delegator和BasicObject之间再次有该模块.因此Delegator不直接派生自BasicObject.如果你查看lib / delegate.rb中的源代码,你会发现: class Delegator < BasicObject kernel = ::Kernel.dup kernel.class_eval do [:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m| undef_method m end end include kernel # ... 所以制作了一个内核模块的副本,它没有to_s,inspect等…但仍然有class和instance_of?.它包含在Delegator中,这就是它们的来源. 请注意,Object通过包含内核模块来继承相同的方法(当然,它包括完整的模块): 42.method(:class) # => #<Method: Fixnum(Kernel)#class> 这在
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |