class SimpleDelegator
Delegator
的一个具体实现,此类提供了将所有支持的方法调用委托给传递给构造函数的对象的方法,甚至可以使用 #__setobj__ 在稍后更改被委托的对象。
class User def born_on Date.new(1989, 9, 10) end end require 'delegate' class UserDecorator < SimpleDelegator def birth_year born_on.year end end decorated_user = UserDecorator.new(User.new) decorated_user.birth_year #=> 1989 decorated_user.__getobj__ #=> #<User: ...>
SimpleDelegator
实例可以利用 SimpleDelegator
是 Delegator
的子类这一事实,调用 super
来对被委托的对象调用方法。
class SuperArray < SimpleDelegator def [](*args) super + 1 end end SuperArray.new([1])[0] #=> 2
这是一个简单的示例,它利用了 SimpleDelegator 的委托对象可以随时更改这一事实。
class Stats def initialize @source = SimpleDelegator.new([]) end def stats(records) @source.__setobj__(records) "Elements: #{@source.size}\n" + " Non-Nil: #{@source.compact.size}\n" + " Unique: #{@source.uniq.size}\n" end end s = Stats.new puts s.stats(%w{James Edward Gray II}) puts puts s.stats([1, 2, 3, nil, 4, 5, 1, 2])
打印
Elements: 4 Non-Nil: 4 Unique: 4 Elements: 8 Non-Nil: 7 Unique: 6
公共实例方法
__getobj__() { || ... } 点击切换源代码
返回当前正在委托方法调用的对象。
# File delegate.rb, line 318 def __getobj__ unless defined?(@delegate_sd_obj) return yield if block_given? __raise__ ::ArgumentError, "not delegated" end @delegate_sd_obj end
__setobj__(obj) 点击切换源代码
将委托对象更改为 obj。
重要的是要注意,这不会导致 SimpleDelegator 的方法发生更改。因此,您可能只想将委托更改为与原始委托类型相同的对象。
这是一个更改委托对象的示例。
names = SimpleDelegator.new(%w{James Edward Gray II}) puts names[1] # => Edward names.__setobj__(%w{Gavin Sinclair}) puts names[1] # => Sinclair
# File delegate.rb, line 340 def __setobj__(obj) __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj) @delegate_sd_obj = obj end