класс 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
Публичные методы экземпляра
# 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 Возвращает текущий объект, к которому делегируются вызовы методов.
# File lib/delegate.rb, line 340 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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.