Spec-Zone.ru › Ruby 3.4

класс Delegator

Родительский класс:
BasicObject

Эта библиотека предоставляет три различных способа делегировать вызовы методов объекту. Проще всего использовать 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

Открытые методы класса

new (obj) Показать исходный код
# File lib/delegate.rb, line 75
def initialize(obj)
  __setobj__(obj)
end

Передайте obj, которому будут делегироваться вызовы методов. Ему будут делегированы все методы, поддерживаемые obj.

Открытые методы экземпляра

! () Показать исходный код
# File lib/delegate.rb, line 180
def !
  !__getobj__
end

Делегирует вызов ! объекту _getobj_

!= (obj) Показать исходный код
# File lib/delegate.rb, line 164
def !=(obj)
  return false if obj.equal?(self)
  __getobj__ != obj
end

Возвращает true, если два объекта не считаются равными по значению.

== (obj) Показать исходный код
# File lib/delegate.rb, line 156
def ==(obj)
  return true if obj.equal?(self)
  self.__getobj__ == obj
end

Возвращает true, если два объекта считаются равными по значению.

__getobj__ () Показать исходный код
# File lib/delegate.rb, line 188
def __getobj__
  __raise__ ::NotImplementedError, "need to define '__getobj__'"
end

Этот метод необходимо переопределить в подклассах. Он должен возвращать объект, которому делегируются вызовы методов.

__raise__ ()
Псевдоним для: raise
__setobj__ (obj) Показать исходный код
# File lib/delegate.rb, line 196
def __setobj__(obj)
  __raise__ ::NotImplementedError, "need to define '__setobj__'"
end

Этот метод необходимо переопределить в подклассах, чтобы изменить объект, которому делегируются вызовы, на obj.

eql? (obj) Показать исходный код
# File lib/delegate.rb, line 172
def eql?(obj)
  return true if obj.equal?(self)
  obj.eql?(__getobj__)
end

Возвращает true, если два объекта считаются равными по значению.

freeze () Показать исходный код
# File lib/delegate.rb, line 237
def freeze
  __getobj__.freeze
  super()
end

:method: freeze Замораживает и объект, возвращаемый _getobj_, и self.

Вызывает метод суперкласса
marshal_dump () Показать исходный код
# 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_.

marshal_load (data) Показать исходный код
# 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

Повторно инициализирует делегирование из сериализованного объекта.

method_missing (m, *args, &block) Показать исходный код
# 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
methods (all=true) Показать исходный код
# File lib/delegate.rb, line 131
def methods(all=true)
  __getobj__.methods(all) | super
end

Возвращает методы, доступные этому объекту-делегату: объединение методов самого объекта и методов _getobj_.

Вызывает метод суперкласса
protected_methods (all=true) Показать исходный код
# File lib/delegate.rb, line 147
def protected_methods(all=true)
  __getobj__.protected_methods(all) | super
end

Возвращает защищённые методы, доступные этому объекту-делегату: объединение защищённых методов самого объекта и защищённых методов _getobj_.

Вызывает метод суперкласса
public_methods (all=true) Показать исходный код
# File lib/delegate.rb, line 139
def public_methods(all=true)
  __getobj__.public_methods(all) | super
end

Возвращает открытые методы, доступные этому объекту-делегату: объединение открытых методов самого объекта и открытых методов _getobj_.

Вызывает метод суперкласса
raise () Показать исходный код
# File lib/delegate.rb, line 66
  

Используйте __raise__, если у вашего Delegator нет объекта, которому можно делегировать вызов метода raise.

Также имеет псевдоним: __raise__
respond_to_missing? (m, include_private) Показать исходный код
# 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_.

Закрытые методы экземпляра

target_respond_to? (target, m, include_private) Показать исходный код
# 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API