首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

SimpleDelegator

Parent:Delegator

Delegator的一个具体实现,该类提供了将所有支持的方法调用委托给传递给构造方法的对象的方法,甚至可以在以后使用#__setobj__更改委派的对象。

代码语言:javascript
复制
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方法的子类,该方法在要委派的对象上调用方法。

代码语言:javascript
复制
class SuperArray < SimpleDelegator
  def [](*args)
    super + 1
  end
end

SuperArray.new([1])[0]  #=> 2

下面是一个简单的例子,它利用了SimpleDelegator的委托对象随时可以更改的事实。

代码语言:javascript
复制
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])

输出:

代码语言:javascript
复制
Elements:  4
 Non-Nil:  4
  Unique:  4

Elements:  8
 Non-Nil:  7
  Unique:  6

公共实例方法

__getobj__() { || ... } Show source

返回正在委派的当前对象方法调用。

代码语言:javascript
复制
# 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的方法改变,这点很重要。因此,您可能只想将委派更改为与原委托相同类型的对象。

以下是更改委托对象的示例。

代码语言:javascript
复制
names = SimpleDelegator.new(%w{James Edward Gray II})
puts names[1]    # => Edward
names.__setobj__(%w{Gavin Sinclair})
puts names[1]    # => Sinclair
代码语言:javascript
复制
# File lib/delegate.rb, line 331
def __setobj__(obj)
  __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
  @delegate_sd_obj = obj
end

扫码关注腾讯云开发者

领取腾讯云代金券