Spec-Zone.ru › Ruby 4.0

модуль Forwardable

Модуль Forwardable предоставляет делегирование указанных методов заданному объекту с помощью методов def_delegator и def_delegators.

Например, предположим, что у вас есть класс RecordCollection, содержащий массив @records. Вы можете предоставить метод поиска record_number(), который просто вызывает [] для массива @records, вот так:

require 'forwardable'

class RecordCollection
  attr_accessor :records
  extend Forwardable
  def_delegator :@records, :[], :record_number
end

Метод поиска можно использовать следующим образом:

r = RecordCollection.new
r.records = [4,5,6]
r.record_number(0)  # => 4

Кроме того, если вы хотите предоставить методы size, << и map, делегирующие вызовы объекту @records, это можно сделать так:

class RecordCollection # re-open RecordCollection class
  def_delegators :@records, :size, :<<, :map
end

r = RecordCollection.new
r.records = [1,2,3]
r.record_number(0)   # => 1
r.size               # => 3
r << 4               # => [1, 2, 3, 4]
r.map { |x| x * 2 }  # => [2, 4, 6, 8]

Вы даже можете расширять обычные объекты с помощью Forwardable.

my_hash = Hash.new
my_hash.extend Forwardable              # prepare object for delegation
my_hash.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
my_hash.puts "Howdy!"

Другой пример

Вы можете использовать Forwardable как альтернативу наследованию, если не хотите наследовать все методы суперкласса. Например, вот как можно добавить набор методов экземпляра Array в новый класс Queue:

class Queue
  extend Forwardable

  def initialize
    @q = [ ]    # prepare delegate object
  end

  # setup preferred interface, enq() and deq()...
  def_delegator :@q, :push, :enq
  def_delegator :@q, :shift, :deq

  # support some general Array methods that fit Queues well
  def_delegators :@q, :clear, :first, :push, :shift, :size
end

q = Thread::Queue.new
q.enq 1, 2, 3, 4, 5
q.push 6

q.shift    # => 1
while q.size > 0
  puts q.deq
end

q.enq "Ruby", "Perl", "Python"
puts q.first
q.clear
puts q.first

Это должно вывести:

2
3
4
5
6
Ruby
nil

Примечания

Обратите внимание: RDoc не обнаруживает делегированные методы.

forwardable.rb предоставляет делегирование отдельных методов с помощью методов def_delegator и def_delegators. Сведения о делегировании всего класса с помощью DelegateClass см. в delegate.rb.

Константы

FORWARDABLE_VERSION

Версия для обратной совместимости

VERSION

Версия forwardable.rb

Атрибуты

debug [RW]

игнорируется

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

def_delegator (accessor, method, ali = method)
Псевдоним для: def_instance_delegator
def_delegators (accessor, *methods)
Псевдоним для: def_instance_delegators
def_instance_delegator (accessor, method, ali = method) Показать исходный код
# File lib/forwardable.rb, line 188
def def_instance_delegator(accessor, method, ali = method)
  gen = Forwardable._delegator_method(self, accessor, method, ali)

  # If it's not a class or module, it's an instance
  mod = Module === self ? self : singleton_class
  mod.module_eval(&gen)
end

Определяет method как метод экземпляра-делегат с необязательным именем псевдонима ali. Вызовы метода ali будут делегированы объекту accessor.method. accessor должно быть именем метода, именем переменной экземпляра или именем константы. Если указано имя константы, используйте полный путь к ней. Возвращает имя определённого метода.

class MyQueue
  CONST = 1
  extend Forwardable
  attr_reader :queue
  def initialize
    @queue = []
  end

  def_delegator :@queue, :push, :mypush
  def_delegator 'MyQueue::CONST', :to_i
end

q = MyQueue.new
q.mypush 42
q.queue    #=> [42]
q.push 23  #=> NoMethodError
q.to_i     #=> 1
Также имеет псевдоним: def_delegator
def_instance_delegators (accessor, *methods) Показать исходный код
# File lib/forwardable.rb, line 156
def def_instance_delegators(accessor, *methods)
  methods.each do |method|
    next if /\A__(?:send|id)__\z/ =~ method
    def_instance_delegator(accessor, method)
  end
end

Сокращённая запись для определения нескольких методов-делегатов без возможности задать для них другие имена. Следующие два примера кода дают одинаковый результат:

def_delegators :@records, :size, :<<, :map

def_delegator :@records, :size
def_delegator :@records, :<<
def_delegator :@records, :map
Также имеет псевдоним: def_delegators
delegate method → accessor
delegate [method, method, ...] → accessor
Псевдоним для: instance_delegate
instance_delegate Показать исходный код
# File lib/forwardable.rb, line 135
def instance_delegate(hash)
  hash.each do |methods, accessor|
    unless defined?(methods.each)
      def_instance_delegator(accessor, methods)
    else
      methods.each {|method| def_instance_delegator(accessor, method)}
    end
  end
end
Также имеет псевдоним: delegate

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