класс Delegator
Эта библиотека предоставляет три различных способа делегирования вызовов методов объекту. Наиболее простой в использовании — SimpleDelegator. Передайте объект в конструктор, и все методы, поддерживаемые объектом, будут делегированы. Этот объект можно изменить позже.
Для достижения более высокого уровня, метод DelegateClass верхнего уровня позволяет легко настроить делегирование через наследование классов. Это значительно гибче и, следовательно, вероятно, является наиболее распространенным применением этой библиотеки.
Наконец, если вам требуется полный контроль над схемой делегирования, вы можете унаследовать от абстрактного класса Delegator и настроить его по мере необходимости. (Если вам потребуется такой контроль, ознакомьтесь с классом Forwardable, который также входит в стандартную библиотеку. Он может лучше соответствовать вашим потребностям.)
Реализация SimpleDelegator служит хорошим примером использования Delegator:
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 не будет обнаруживать делегированные методы.
Общедоступные методы класса
# File lib/delegate.rb, line 70 def initialize(obj) __setobj__(obj) end
Передайте obj для делегирования вызовов методов. Все методы, поддерживаемые obj, будут делегированы.
Общедоступные методы экземпляра
# File lib/delegate.rb, line 158 def ! !__getobj__ end
Делегирует ! в _getobj_
# File lib/delegate.rb, line 142 def !=(obj) return false if obj.equal?(self) __getobj__ != obj end
Возвращает true, если два объекта не считаются равными.
# File lib/delegate.rb, line 134 def ==(obj) return true if obj.equal?(self) self.__getobj__ == obj end
Возвращает true, если два объекта считаются равными.
# File lib/delegate.rb, line 166 def __getobj__ __raise__ ::NotImplementedError, "need to define `__getobj__'" end
Этот метод должен быть переопределен подклассами и должен возвращать объект, к которому делегируются вызовы методов.
# File lib/delegate.rb, line 174 def __setobj__(obj) __raise__ ::NotImplementedError, "need to define `__setobj__'" end
Этот метод должен быть переопределен подклассами и изменить объект-делегат на obj.
# File lib/delegate.rb, line 150 def eql?(obj) return true if obj.equal?(self) obj.eql?(__getobj__) end
Возвращает true, если два объекта считаются равными.
# File lib/delegate.rb, line 236
Замораживает как объект, возвращаемый _getobj_, так и self.
# File lib/delegate.rb, line 181
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 193
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 77
def method_missing(m, *args, &block)
r = true
target = self.__getobj__ {r = false}
if r && target.respond_to?(m)
target.__send__(m, *args, &block)
elsif ::Kernel.respond_to?(m, true)
::Kernel.instance_method(m).bind(self).(*args, &block)
else
super(m, *args, &block)
end
end Обрабатывает магию делегирования через _getobj_.
# File lib/delegate.rb, line 109 def methods(all=true) __getobj__.methods(all) | super end
Возвращает методы, доступные этому объекту-делегату, как объединение методов этого объекта и _getobj_.
# File lib/delegate.rb, line 125 def protected_methods(all=true) __getobj__.protected_methods(all) | super end
Возвращает защищенные методы, доступные этому объекту-делегату, как объединение методов этого объекта и защищенных методов _getobj_.
# File lib/delegate.rb, line 117 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 94
def respond_to_missing?(m, include_private)
r = true
target = self.__getobj__ {r = false}
r &&= target.respond_to?(m, include_private)
if r && include_private && !target.respond_to?(m, false)
warn "delegator does not forward private method \##{m}", uplevel: 3
return false
end
r
end Проверяет наличие метода, предоставляемого делегированным объектом, перенаправляя вызов через _getobj_.
# File lib/delegate.rb, line 226
Пометить как небезопасный (таинт) и объект, возвращаемый _getobj_, и self.
# File lib/delegate.rb, line 216
Доверить и объект, возвращаемый _getobj_, и self.
# File lib/delegate.rb, line 231
Снять помечен как небезопасный (untaint) и объект, возвращаемый _getobj_, и self.
# File lib/delegate.rb, line 221
Снять доверие и к объекту, возвращаемому _getobj_, и к self.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.