класс 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 71 def initialize(obj) __setobj__(obj) end
Передайте obj для делегирования вызовов методов. Все методы, поддерживаемые obj, будут делегированы.
Методы экземпляра
# File lib/delegate.rb, line 151 def ! !__getobj__ end
Делегирует ! в _getobj_
# File lib/delegate.rb, line 143 def !=(obj) return false if obj.equal?(self) __getobj__ != obj end
Возвращает true, если два объекта не считаются равными по значению.
# File lib/delegate.rb, line 135 def ==(obj) return true if obj.equal?(self) self.__getobj__ == obj end
Возвращает true, если два объекта считаются равными по значению.
# File lib/delegate.rb, line 159 def __getobj__ __raise__ ::NotImplementedError, "need to define `__getobj__'" end
Этот метод должен быть переопределен подклассами и должен возвращать объект, к которому делегируются вызовы методов.
# File lib/delegate.rb, line 167 def __setobj__(obj) __raise__ ::NotImplementedError, "need to define `__setobj__'" end
Этот метод должен быть переопределен подклассами и изменить объект-делегат на obj.
# File lib/delegate.rb, line 229
Заморозить как объект, возвращаемый _getobj_, так и сам себя.
# File lib/delegate.rb, line 174
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 186
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 78
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 110 def methods(all=true) __getobj__.methods(all) | super end
Возвращает доступные для этого объекта-делегата методы как объединение методов этого объекта и _getobj_.
# File lib/delegate.rb, line 126 def protected_methods(all=true) __getobj__.protected_methods(all) | super end
Возвращает доступные для этого объекта-делегата методы как объединение защищенных методов этого объекта и _getobj_.
# File lib/delegate.rb, line 118 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 95
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 "#{caller(3)[0]}: delegator does not forward private method \##{m}"
return false
end
r
end Проверяет наличие метода, предоставленного объектом-делегированием, перенаправляя вызов через _getobj_.
# File lib/delegate.rb, line 219
Пометить как небезопасный и сам объект, возвращаемый _getobj_, и текущий объект.
# File lib/delegate.rb, line 209
Доверие и к объекту, возвращаемому _getobj_, и к текущему объекту.
# File lib/delegate.rb, line 224
Снять метку небезопасности как с объекта, возвращаемого _getobj_, так и с текущего объекта.
# File lib/delegate.rb, line 214
Убрать доверие и к объекту, возвращаемому _getobj_, и к текущему объекту.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.