класс Delegator
Эта библиотека предоставляет три различных способа делегирования вызовов методов объекту. Проще всего использовать SimpleDelegator. Передайте объект конструктору, и ему будут делегированы все методы, поддерживаемые этим объектом. Позже этот объект можно заменить.
Следующий уровень — метод верхнего уровня DelegateClass, который позволяет легко настроить делегирование посредством наследования классов. Это значительно гибче, поэтому, вероятно, данный способ чаще всего используют в этой библиотеке.
Наконец, если вам нужен полный контроль над механизмом делегирования, можно унаследоваться от абстрактного класса Delegator и настроить его по своему усмотрению. (Если вам понадобится такой контроль, обратите внимание на Forwardable, который также входит в стандартную библиотеку. Возможно, он лучше подойдет для ваших задач.)
Реализация SimpleDelegator служит наглядным примером использования Delegator:
require 'delegate'
class SimpleDelegator < Delegator
def __getobj__
@delegate_sd_obj # return object we are delegating to, required
end
def __setobj__(obj)
@delegate_sd_obj = obj # change delegation object,
# a feature we're providing
end
end
Примечания
Обратите внимание: RDoc не обнаруживает делегируемые методы.
Константы
- VERSION
-
Строка версии
Публичные методы класса
# File lib/delegate.rb, line 76 def initialize(obj) __setobj__(obj) end
Передайте obj, которому нужно делегировать вызовы методов. Ему будут делегированы все методы, поддерживаемые obj.
Публичные методы экземпляра
# File lib/delegate.rb, line 181 def ! !__getobj__ end
Делегирует вызов ! объекту __getobj__
# File lib/delegate.rb, line 165 def !=(obj) return false if obj.equal?(self) __getobj__ != obj end
Возвращает true, если два объекта не считаются равными по значению.
# File lib/delegate.rb, line 157 def ==(obj) return true if obj.equal?(self) self.__getobj__ == obj end
Возвращает true, если два объекта считаются равными по значению.
# File lib/delegate.rb, line 189 def __getobj__ __raise__ ::NotImplementedError, "need to define '__getobj__'" end
Этот метод должен быть переопределен подклассами и должен возвращать объект, которому делегируются вызовы методов.
# File lib/delegate.rb, line 197 def __setobj__(obj) __raise__ ::NotImplementedError, "need to define '__setobj__'" end
Этот метод должен быть переопределен подклассами и должен переключать делегирование объекта на obj.
# File lib/delegate.rb, line 173 def eql?(obj) return true if obj.equal?(self) obj.eql?(__getobj__) end
Возвращает true, если два объекта считаются равными по значению.
# File lib/delegate.rb, line 238 def freeze __getobj__.freeze super() end
:method: freeze Замораживает объект, возвращаемый методом __getobj__, и сам объект.
# File lib/delegate.rb, line 204
def marshal_dump
ivars = instance_variables.reject {|var| /\A@delegate_/ =~ var}
[
:__v2__,
ivars, ivars.map {|var| instance_variable_get(var)},
__getobj__
]
end Поддержка сериализации объекта, возвращаемого методом __getobj__.
# File lib/delegate.rb, line 216
def marshal_load(data)
version, vars, values, obj = data
if version == :__v2__
vars.each_with_index {|var, i| instance_variable_set(var, values[i])}
__setobj__(obj)
else
__setobj__(data)
end
end Повторно инициализирует делегирование на основе сериализованного объекта.
# File lib/delegate.rb, line 83
def method_missing(m, *args, &block)
r = true
target = self.__getobj__ {r = false}
if r && target_respond_to?(target, m, false)
target.__send__(m, *args, &block)
elsif ::Kernel.method_defined?(m) || ::Kernel.private_method_defined?(m)
::Kernel.instance_method(m).bind_call(self, *args, &block)
else
super(m, *args, &block)
end
end BasicObject#method_missing # File lib/delegate.rb, line 132 def methods(all=true) __getobj__.methods(all) | super end
Возвращает методы, доступные этому объекту-делегату: объединение методов самого объекта и методов __getobj__.
# File lib/delegate.rb, line 148 def protected_methods(all=true) __getobj__.protected_methods(all) | super end
Возвращает защищенные методы, доступные этому объекту-делегату: объединение защищенных методов самого объекта и защищенных методов __getobj__.
# File lib/delegate.rb, line 140 def public_methods(all=true) __getobj__.public_methods(all) | super end
Возвращает публичные методы, доступные этому объекту-делегату: объединение публичных методов самого объекта и публичных методов __getobj__.
# File lib/delegate.rb, line 67
Используйте __raise__, если у вашего Delegator нет объекта, которому можно делегировать вызов метода raise.
# File lib/delegate.rb, line 100
def respond_to_missing?(m, include_private)
r = true
target = self.__getobj__ {r = false}
r &&= target_respond_to?(target, m, include_private)
if r && include_private && !target_respond_to?(target, m, false)
warn "delegator does not forward private method \##{m}", uplevel: 3
return false
end
r
end Проверяет, предоставляет ли объект-делегат этот метод, перенаправляя вызов через __getobj__.
Приватные методы экземпляра
# File lib/delegate.rb, line 115
def target_respond_to?(target, m, include_private)
case target
when Object
target.respond_to?(m, include_private)
else
if KERNEL_RESPOND_TO.bind_call(target, :respond_to?)
target.respond_to?(m, include_private)
else
KERNEL_RESPOND_TO.bind_call(target, m, include_private)
end
end
end Обрабатывает экземпляры BasicObject
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.