Delegator 类
此库提供了三种不同的方法来将方法调用委托给对象。最简单的方法是使用 SimpleDelegator
。将一个对象传递给构造函数,所有对象支持的方法都将被委托。此对象之后可以更改。
更进一步,顶级 DelegateClass 方法允许你轻松地通过类继承来设置委托。这更加灵活,因此可能是此库最常见的用法。
最后,如果你需要完全控制委托方案,你可以从抽象类 Delegator
继承并根据需要进行自定义。(如果你发现自己需要此控制,请查看 Forwardable
,它也在标准库中。它可能更适合你的需求。)
SimpleDelegator 的实现是 Delegator 使用的一个很好的示例
require 'delegate' class SimpleDelegator < Delegator def __getobj__ @delegate_sd_obj # return object we are delegating to, required end def __setobj__(obj) @delegate_sd_obj = obj # change delegation object, # a feature we're providing end end
注释¶ ↑
请注意,RDoc
不会检测委托的方法。
常量
- KERNEL_RESPOND_TO
- VERSION
公共类方法
new(obj) 点击切换源代码
传入要将方法调用委托到的 obj。obj 支持的所有方法都将被委托。
# File lib/delegate.rb, line 75 def initialize(obj) __setobj__(obj) end
公共实例方法
!() 点击切换源代码
将 ! 委托给 _getobj_
# File lib/delegate.rb, line 180 def ! !__getobj__ end
!=(obj) 点击切换源代码
如果两个对象不被视为相等,则返回 true。
# File lib/delegate.rb, line 164 def !=(obj) return false if obj.equal?(self) __getobj__ != obj end
==(obj) 点击切换源代码
如果两个对象被视为相等,则返回 true。
# File lib/delegate.rb, line 156 def ==(obj) return true if obj.equal?(self) self.__getobj__ == obj end
__getobj__() 点击切换源代码
此方法必须被子类覆盖,并且应该返回方法调用被委托到的对象。
# File lib/delegate.rb, line 188 def __getobj__ __raise__ ::NotImplementedError, "need to define `__getobj__'" end
__setobj__(obj) 单击切换源
子类必须覆盖此方法,并将对象委托更改为obj。
# File lib/delegate.rb, line 196 def __setobj__(obj) __raise__ ::NotImplementedError, "need to define `__setobj__'" end
eql?(obj) 单击切换源
如果两个对象被视为相等,则返回 true。
# File lib/delegate.rb, line 172 def eql?(obj) return true if obj.equal?(self) obj.eql?(__getobj__) end
freeze() 单击切换源
:method: freeze 冻结 _getobj_ 返回的对象和自身。
调用超类方法
# File lib/delegate.rb, line 237 def freeze __getobj__.freeze super() end
marshal_dump() 单击切换源
_getobj_ 返回的对象的序列化支持。
# File lib/delegate.rb, line 203 def marshal_dump ivars = instance_variables.reject {|var| /\A@delegate_/ =~ var} [ :__v2__, ivars, ivars.map {|var| instance_variable_get(var)}, __getobj__ ] end
marshal_load(data) 单击切换源
从序列化对象重新初始化委托。
# File lib/delegate.rb, line 215 def marshal_load(data) version, vars, values, obj = data if version == :__v2__ vars.each_with_index {|var, i| instance_variable_set(var, values[i])} __setobj__(obj) else __setobj__(data) end end
method_missing(m, *args, &block) 单击切换源
调用超类方法
BasicObject#method_missing
# File lib/delegate.rb, line 82 def method_missing(m, *args, &block) r = true target = self.__getobj__ {r = false} if r && target_respond_to?(target, m, false) target.__send__(m, *args, &block) elsif ::Kernel.method_defined?(m) || ::Kernel.private_method_defined?(m) ::Kernel.instance_method(m).bind_call(self, *args, &block) else super(m, *args, &block) end end
methods(all=true) 单击切换源
将此对象的和 _getobj_ 方法的并集作为此委托对象可用的方法返回。
调用超类方法
# File lib/delegate.rb, line 131 def methods(all=true) __getobj__.methods(all) | super end
protected_methods(all=true) 单击切换源
将此对象的和 _getobj_ 受保护方法的并集作为此委托对象可用的方法返回。
调用超类方法
# File lib/delegate.rb, line 147 def protected_methods(all=true) __getobj__.protected_methods(all) | super end
public_methods(all=true) 单击切换源
将此对象的和 _getobj_ 公共方法的并集作为此委托对象可用的方法返回。
调用超类方法
# File lib/delegate.rb, line 139 def public_methods(all=true) __getobj__.public_methods(all) | super end
raise() 单击切换源
别名:__raise__
respond_to_missing?(m, include_private) 单击切换源
通过转发调用到 _getobj_,检查此委托对象提供的方法。
# File lib/delegate.rb, line 99 def respond_to_missing?(m, include_private) r = true target = self.__getobj__ {r = false} r &&= target_respond_to?(target, m, include_private) if r && include_private && !target_respond_to?(target, m, false) warn "delegator does not forward private method \##{m}", uplevel: 3 return false end r end
私有实例方法
target_respond_to?(target, m, include_private) 单击切换源
处理 BasicObject
实例
# File lib/delegate.rb, line 114 def target_respond_to?(target, m, include_private) case target when Object target.respond_to?(m, include_private) else if KERNEL_RESPOND_TO.bind_call(target, :respond_to?) target.respond_to?(m, include_private) else KERNEL_RESPOND_TO.bind_call(target, m, include_private) end end end