Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

Библиотека

delegate
предлагает три способа решения задачи. Класс
SimpleDelegator
полезен, когда объект, которому делегируется управление (делегат), может изменяться на протяжении времени жизни делегирующего объекта. Чтобы выбрать объект-делегат, используется метод
__setobj__
.

Однако мне этот способ представляется слишком примитивным. Поскольку я не думаю, что это существенно лучше, чем то же самое, сделанное вручную, задерживаться на классе

SimpleDelegator
не стану.

Метод верхнего уровня

DelegateClass
принимает в качестве параметра класс, которому делегируется управление. Затем он создает новый класс, которому мы можем унаследовать. Вот пример создания класса
Queue
, который делегирует объекту
Array
:

require 'delegate'

class MyQueue < DelegateClass(Array)

 def initialize(arg=[])

super(arg)

 end

 alias_method :enqueue, :push

 alias_method :dequeue, :shift

end

mq = MyQueue.new

mq.enqueue(123)

mq.enqueue(234)

p mq.dequeue # 123

p mq.dequeue # 234

Можно также унаследовать класс

Delegator
и реализовать метод
__getobj__
; именно таким образом реализован класс
SimpleDelegator
. При этом мы получаем больший контроль над делегированием.

Но если вам необходим больший контроль, то, вероятно, вы все равно осуществляете делегирование на уровне отдельных методов, а не класса в целом. Тогда лучше воспользоваться библиотекой

forwardable
. Вернемся к примеру очереди:

require 'forwardable'

class MyQueue

 extend Forwardable

 def initialize(obj=[])

@queue = obj # Делегировать этому объекту.

 end

 def_delegator :@queue, :push, :enqueue

 def_delegator :@queue, :shift, :dequeue

 def_delegators :@queue, :clear, :empty?, :length, :size, :<<

 # Прочий код...

end

Как видно из этого примера, метод

def_delegator
ассоциирует вызов метода (скажем,
enqueue
) с объектом-делегатом
@queue
и одним из методов этого объекта (
push
).
Иными словами, когда мы вызываем метод
enqueue
для объекта
MyQueue
, производится делегирование методу push объекта
@queue
(который обычно является массивом).

Обратите внимание, мы пишем

:@queue
, а не
:queue
или
@queue
. Объясняется это тем, как написан класс
Forwardable
; можно было бы сделать и по-другому.

Иногда нужно делегировать методы одного объекта одноименным методам другого объекта. Метод

def_delegators
позволяет задать произвольное число таких методов. Например, в примере выше показано, что вызов метода
length
объекта
MyQueue
приводит к вызову метода
length
объекта
@queue
.

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

[]
или
[]=
для очереди; если вы так поступаете, то очередь перестает быть очередью.

Отметим еще, что показанный выше код позволяет вызывающей программе передавать объект конструктору (для использования в качестве объекта-делегата). В полном соответствии с духом «утилизации» это означает, что я могу выбирать вид объекта, которому делегируется управление, коль скоро он поддерживает те методы, которые вызываются в программе.

Например, все приведенные ниже вызовы допустимы. (В последних двух предполагается, что предварительно было выполнено предложение

require 'thread'
.)

q1 = MyQueue.new # Используется любой массив.

q2 = MyQueue.new(my_array) # Используется конкретный массив.

q3 = MyQueue.new(Queue.new) # Используется Queue (thread.rb).

q4 = MyQueue.new(SizedQueue.new) # Используется SizedQueue (thread.rb).

Так, объекты

q3
и
q4
волшебным образом становятся безопасными относительно потоков, поскольку делегируют управление безопасному в этом отношении объекту (если, конечно, какой-нибудь не показанный здесь код не нарушит эту гарантию).

Существует также класс

SingleForwardable
, который воздействует на один экземпляр, а не на класс в целом. Это полезно, если вы хотите, чтобы какой-то конкретный объект делегировал управление другому объекту, а все остальные объекты того же класса так не поступали.

Быть может, вы задумались о том, что лучше — делегирование или наследование. Но это неправильный вопрос. В некоторых ситуациях делегирование оказывается более подходящим решением. Предположим, к примеру, что имеется класс, у которого уже есть родитель. Унаследовать еще от одного родителя мы не можем (в Ruby множественное наследование запрещено), но делегирование в той или иной форме вполне допустимо.

11.2.10. Автоматическое определение методов чтения и установки на уровне класса

Поделиться:
Популярные книги

Покер для даймонов. Тетралогия

Бульба Наталья Владимировна
107. В одном томе
Фантастика:
фэнтези
8.55
рейтинг книги
Покер для даймонов. Тетралогия

"Господин мертвец"

Соловьев Константин Сергеевич
2. Господа Магильеры
Фантастика:
боевая фантастика
5.00
рейтинг книги
Господин мертвец

Потемкин

Елисеева Ольга Игоревна
916. Жизнь замечательных людей
Проза:
историческая проза
5.00
рейтинг книги
Потемкин

Неучтенный элемент. Том 3

NikL
3. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 3

Воронцов. Перезагрузка

Тарасов Ник
1. Воронцов. Перезагрузка
Фантастика:
попаданцы
альтернативная история
фантастика: прочее
5.50
рейтинг книги
Воронцов. Перезагрузка

Последний рейд

Сай Ярослав
5. Медорфенов
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Последний рейд

Играть... в тебя

Зайцева Мария
3. Звериные повадки Симоновых
Любовные романы:
современные любовные романы
5.25
рейтинг книги
Играть... в тебя

Маленькая женщина Большого

Зайцева Мария
5. Наша
Любовные романы:
эро литература
современные любовные романы
5.40
рейтинг книги
Маленькая женщина Большого

Булгаков

Варламов Алексей Николаевич
Проза:
историческая проза
современная проза
повесть
5.00
рейтинг книги
Булгаков

Печать Пожирателя

Соломенный Илья
1. Пожиратель
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Печать Пожирателя

Стихотворения 1906-1941

Цветаева Марина Ивановна
Поэзия:
поэзия
5.00
рейтинг книги
Стихотворения 1906-1941

Я до сих пор не царь. Книга XXVII

Дрейк Сириус
27. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я до сих пор не царь. Книга XXVII

Кодекс Охотника. Книга XXXIV

Винокуров Юрий
34. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXIV

Корона Тафелона

Авербух Наталья Владимировна
3. Ведьмина дорога
Фантастика:
фэнтези
5.00
рейтинг книги
Корона Тафелона