類別 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 lib/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 lib/delegate.rb, line 340 def __setobj__(obj) __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj) @delegate_sd_obj = obj end