Программирование на языке Ruby
Программирование на языке Ruby читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
umeth = String.instance_method(:length)m1 = umeth.bind("cat")m1.call # 3m2 = umeth.bind("caterpillar")m2.call # 11Явное связывание делает объект
UnboundMethodMethod11.2.7. Как работает включение модулей?
Когда модуль включается в класс, Ruby на самом деле создает прокси-класс, являющийся непосредственным родителем данного класса. Возможно, вам это покажется интуитивно очевидным, возможно, нет. Все методы включаемого модуля «маскируются» методами, определенными в классе.
module MyMod def meth "из модуля" endendclass ParentClass def meth "из родителя" endendclass ChildClass < ParentClass include MyMod def meth "из потомка" endendx = ChildClass.new pp x.meth # Из потомка.Выглядит это как настоящее наследование: все, что потомок переопределил, становится действующим определением вне зависимости от того, вызывается ли
includeВот похожий пример, в котором метод потомка вызывает
super# Модуль MyMod и класс ParentClass не изменились.class ChildClass < ParentClass include MyMod def meth "Из потомка: super = " + super endendx = ChildClass.newp x.meth # Из потомка: super = из модуляОтсюда видно, что модуль действительно является новым родителем класса. А что если мы точно также вызовем
supermodule MyMod def meth "Из модуля: super = " + super endend# ParentClass не изменился.class ChildClass < ParentClass include MyMod def meth "Из потомка: super = " + super endendx = ChildClass.newp x.meth # Из потомка: super = из модуля: super = из родителя.Метод
methMyModsupermethmodule MyMod def meth "Из модуля: super = " + super endendclass Foo include MyModendx = Foo.newx.methПри выполнении этого кода мы получили бы ошибку
NoMethodErrormethod_missing11.2.8. Опознание параметров, заданных по умолчанию
В 2004 году Ян Макдональд (Ian Macdonald) задал в списке рассылки вопрос: «Можно ли узнать, был ли параметр задан вызывающей программой или взято значение по умолчанию?» Вопрос интересный. Не каждый день он возникает, но от того не менее интересен.
Было предложено по меньшей мере три решения. Самое удачное и простое нашел Нобу Накада (Nobu Nakada). Оно приведено ниже:
def meth(a, b=(flag=true; 345)) puts "b равно #{b}, a flag равно #{flag.inspect}"endmeth(123) # b равно 345, a flag равно truemeth(123,345) # b равно 345, a flag равно nilmeth(123,456) # b равно 456, a flag равно nilКак видим, этот подход работает даже, если вызывающая программа явно указала значение параметра, совпадающее с подразумеваемым по умолчанию. Трюк становится очевидным, едва вы его увидите: выражение в скобках устанавливает локальную переменную
flagtrue11.2.9. Делегирование или перенаправление
В Ruby есть две библиотеки, которые предлагают решение задачи о делегировании или перенаправлении вызовов методов другому объекту. Они называются
delegateforwardableБиблиотека
delegateSimpleDelegator__setobj__
