Spec-Zone.ru › Ruby 2.5

класс SimpleDelegator

Родитель:
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__() { || ... } Показать исходный код
# File lib/delegate.rb, line 317
def __getobj__
  unless defined?(@delegate_sd_obj)
    return yield if block_given?
    __raise__ ::ArgumentError, "not delegated"
  end
  @delegate_sd_obj
end

Возвращает текущий объект, к которому делегируются вызовы методов.

__setobj__(obj) Показать исходный код
# File lib/delegate.rb, line 339
def __setobj__(obj)
  __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
  @delegate_sd_obj = obj
end

Изменяет делегируемый объект на obj.

Важно отметить, что это не приводит к изменению методов SimpleDelegator. По этой причине вы, вероятно, захотите изменить делегирование только на объекты того же типа, что и исходный делегат.

Вот пример изменения делегируемого объекта.

names = SimpleDelegator.new(%w{James Edward Gray II})
puts names[1]    # => Edward
names.__setobj__(%w{Gavin Sinclair})
puts names[1]    # => Sinclair

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API