модуль 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
Атрибуты
игнорируется
Открытые методы экземпляра
# 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
# 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
# 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
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.