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

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

Жанры

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

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

Последний Паладин. Том 13

Саваровский Роман
13. Путь Паладина
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 13

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

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

Неудержимый. Книга XXXVII

Боярский Андрей
37. Неудержимый
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXXVII

Тень правды

Алмазов Игорь
9. Жизнь Лекаря с нуля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Тень правды

#Бояръ-Аниме. Газлайтер. Том 37

Володин Григорий Григорьевич
37. История Телепата
Фантастика:
фэнтези
аниме
боевая фантастика
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 37

Первый среди равных. Книга IX

Бор Жорж
9. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга IX

Моя Академия

Листратов Валерий
1. Академка
Фантастика:
попаданцы
сказочная фантастика
фэнтези
4.50
рейтинг книги
Моя Академия

Практик

Листратов Валерий
5. Ушедший Род
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Практик

Телохранитель Генсека. Том 3

Алмазный Петр
3. Медведев
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Телохранитель Генсека. Том 3

Личный аптекарь императора

Карелин Сергей Витальевич
1. Личный аптекарь императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Личный аптекарь императора

Рубежник

Билик Дмитрий Александрович
1. Бедовый
Фантастика:
юмористическая фантастика
городское фэнтези
мистика
5.00
рейтинг книги
Рубежник

Господин из завтра. Тетралогия.

Махров Алексей
Фантастика:
альтернативная история
8.32
рейтинг книги
Господин из завтра. Тетралогия.

Жрец Хаоса. Книга II

Борзых М.
2. Зов пустоты
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Жрец Хаоса. Книга II

Тьма и Хаос

Владимиров Денис
6. Глэрд
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Тьма и Хаос