класс 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 не будет обнаруживать делегированные методы.
Константы
- KERNEL_RESPOND_TO
Методы класса
# File lib/delegate.rb, line 71 def initialize(obj) __setobj__(obj) end
Передайте obj для делегирования вызовов методов. Все методы, поддерживаемые obj, будут делегированы.
Методы экземпляра
# File lib/delegate.rb, line 176 def ! !__getobj__ end
Делегирует ! в _getobj_
# File lib/delegate.rb, line 160 def !=(obj) return false if obj.equal?(self) __getobj__ != obj end
Возвращает true, если два объекта не считаются равными.
# File lib/delegate.rb, line 152 def ==(obj) return true if obj.equal?(self) self.__getobj__ == obj end
Возвращает true, если два объекта считаются равными.
# File lib/delegate.rb, line 184 def __getobj__ __raise__ ::NotImplementedError, "need to define `__getobj__'" end
Этот метод должен быть переопределён подклассами и должен возвращать объект, к которому делегируются вызовы методов.
# File lib/delegate.rb, line 192 def __setobj__(obj) __raise__ ::NotImplementedError, "need to define `__setobj__'" end
Этот метод должен быть переопределён подклассами и изменить объект-делегат на obj.
# File lib/delegate.rb, line 168 def eql?(obj) return true if obj.equal?(self) obj.eql?(__getobj__) end
Возвращает true, если два объекта считаются равными.
# File lib/delegate.rb, line 233 def freeze __getobj__.freeze super() end
:method: freeze Замораживает как объект, возвращаемый _getobj_, так и self.
# File lib/delegate.rb, line 199
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 211
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?(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 127 def methods(all=true) __getobj__.methods(all) | super end
Возвращает методы, доступные для этого объекта-делегата, как объединение методов этого объекта и _getobj_.
# File lib/delegate.rb, line 143 def protected_methods(all=true) __getobj__.protected_methods(all) | super end
Возвращает защищённые методы, доступные для этого объекта-делегата, как объединение защищённых методов этого объекта и _getobj_.
# File lib/delegate.rb, line 135 def public_methods(all=true) __getobj__.public_methods(all) | super end
Возвращает публичные методы, доступные для этого объекта-делегата, как объединение публичных методов этого объекта и _getobj_.
# File lib/delegate.rb, line 62
Используйте #__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?(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 110
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–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.