SimpleDelegator
class SimpleDelegator
Parent:Delegator
Delegator的一个具体实现,该类提供了将所有支持的方法调用委托给传递给构造方法的对象的方法,甚至可以在以后使用#__setobj__更改委派的对象。
class User
def born_on
Date.new(1989, 9, 10)
end
end
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__() { || ... } Show source
返回正在委派的当前对象方法调用。
# File lib/delegate.rb, line 309
def __getobj__
unless defined?(@delegate_sd_obj)
return yield if block_given?
__raise__ ::ArgumentError, "not delegated"
end
@delegate_sd_obj
end
__setobj__(obj) Show source
将委托对象更改为obj
。
需要注意的是,这并不会
导致SimpleDelegator的方法改变,这点很重要。因此,您可能只想将委派更改为与原委托相同类型的对象。
以下是更改委托对象的示例。
names = SimpleDelegator.new(%w{James Edward Gray II})
puts names[1] # => Edward
names.__setobj__(%w{Gavin Sinclair})
puts names[1] # => Sinclair
# File lib/delegate.rb, line 331
def __setobj__(obj)
__raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
@delegate_sd_obj = obj
end