класс 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 не обнаруживает делегированные методы.
Константы
- KERNEL_RESPOND_TO
- VERSION
Открытые методы класса
# File lib/delegate.rb, line 75 def initialize(obj) __setobj__(obj) end
Передайте obj, которому будут делегироваться вызовы методов. Ему будут делегированы все методы, поддерживаемые obj.
Открытые методы экземпляра
# File lib/delegate.rb, line 180 def ! !__getobj__ end
Делегирует вызов ! объекту _getobj_
# File lib/delegate.rb, line 164 def !=(obj) return false if obj.equal?(self) __getobj__ != obj end
Возвращает true, если два объекта не считаются равными по значению.
# File lib/delegate.rb, line 156 def ==(obj) return true if obj.equal?(self) self.__getobj__ == obj end
Возвращает true, если два объекта считаются равными по значению.
# File lib/delegate.rb, line 188 def __getobj__ __raise__ ::NotImplementedError, "need to define '__getobj__'" end
Этот метод необходимо переопределить в подклассах. Он должен возвращать объект, которому делегируются вызовы методов.
# File lib/delegate.rb, line 196 def __setobj__(obj) __raise__ ::NotImplementedError, "need to define '__setobj__'" end
Этот метод необходимо переопределить в подклассах, чтобы изменить объект, которому делегируются вызовы, на obj.
# File lib/delegate.rb, line 172 def eql?(obj) return true if obj.equal?(self) obj.eql?(__getobj__) end
Возвращает true, если два объекта считаются равными по значению.
# File lib/delegate.rb, line 237 def freeze __getobj__.freeze super() end
:method: freeze Замораживает и объект, возвращаемый _getobj_, и self.
# File lib/delegate.rb, line 203
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 215
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 82
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 131 def methods(all=true) __getobj__.methods(all) | super end
Возвращает методы, доступные этому объекту-делегату: объединение методов самого объекта и методов _getobj_.
# File lib/delegate.rb, line 147 def protected_methods(all=true) __getobj__.protected_methods(all) | super end
Возвращает защищённые методы, доступные этому объекту-делегату: объединение защищённых методов самого объекта и защищённых методов _getobj_.
# File lib/delegate.rb, line 139 def public_methods(all=true) __getobj__.public_methods(all) | super end
Возвращает открытые методы, доступные этому объекту-делегату: объединение открытых методов самого объекта и открытых методов _getobj_.
# File lib/delegate.rb, line 66
Используйте __raise__, если у вашего Delegator нет объекта, которому можно делегировать вызов метода raise.
# File lib/delegate.rb, line 99
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 114
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.