Программирование на языке Ruby
Программирование на языке Ruby читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Однако мне этот способ представляется слишком примитивным. Поскольку я не думаю, что это существенно лучше, чем то же самое, сделанное вручную, задерживаться на классе
SimpleDelegatorМетод верхнего уровня
DelegateClassQueueArrayrequire 'delegate'class MyQueue < DelegateClass(Array) def initialize(arg=[]) super(arg) end alias_method :enqueue, :push alias_method :dequeue, :shiftendmq = MyQueue.newmq.enqueue(123)mq.enqueue(234)p mq.dequeue # 123p mq.dequeue # 234Можно также унаследовать класс
Delegator__getobj__SimpleDelegatorНо если вам необходим больший контроль, то, вероятно, вы все равно осуществляете делегирование на уровне отдельных методов, а не класса в целом. Тогда лучше воспользоваться библиотекой
forwardablerequire '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_delegatorenqueue@queuepushenqueueMyQueue@queueОбратите внимание, мы пишем
:@queue:queue@queueForwardableИногда нужно делегировать методы одного объекта одноименным методам другого объекта. Метод
def_delegatorslengthMyQueuelength@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).Так, объекты
q3q4Существует также класс
SingleForwardableБыть может, вы задумались о том, что лучше — делегирование или наследование. Но это неправильный вопрос. В некоторых ситуациях делегирование оказывается более подходящим решением. Предположим, к примеру, что имеется класс, у которого уже есть родитель. Унаследовать еще от одного родителя мы не можем (в Ruby множественное наследование запрещено), но делегирование в той или иной форме вполне допустимо.
11.2.10. Автоматическое определение методов чтения и установки на уровне класса
Мы уже рассматривали методы
attr_readerattr_writerattr_accessorВ Ruby нет аналогичных средств для их автоматического создания. Но можно написать нечто подобное самостоятельно.
В первом издании этой книги была показана хитроумная схема на основе метода
class_evalcattr_readercattr_writerНо есть более простой путь. Откроем синглетный класс и воспользуемся в нем семейством методов
attr
