myproc = Proc.new { |a| puts 'Параметр равен #{а}' }

myproc.call(99) # Параметр равен 99

Кроме того, Ruby автоматически создает объект Proc, когда метод, последний параметр которого помечен амперсандом, вызывается с блоком в качестве параметра:

def take_block(x, &block)

 puts block.class

 x.times {|i| block[i, i*i] }

end

take_block(3) { |n,s| puts '#{n} в квадрате равно #{s}' }

В этом примере демонстрируется также применение квадратных скобок как синонима метода call. Вот что выводится в результате исполнения:

Proc

0 в квадрате 0

1 в квадрате 1

2 в квадрате 4

Объект Proc можно передавать методу, который ожидает блок, предварив имя знаком &:

myproc = proc { |n| print n, '... ' }

(1..3).each(&myproc) # 1... 2... 3...

Ruby позволяет также превратить метод в объект. Исторически для этого применяется метод Object#method, который создает объект класса Method как замыкание в конкретном объекте.

str = 'cat'

meth = str.method(:length)

a = meth.call # 3 (длина 'cat')

str << 'erpillar'

b = meth.call # 11 (длина 'caterpillar')

str = 'dog'

# Обратите внимание на следующий вызов! Переменная str теперь ссылается

# на новый объект ('dog'), но meth по-прежнему связан со старым объектом.

с = meth.call # 11 (длина 'caterpillar')

Начиная с версии Ruby 1.6.2, можно также применять метод Module#instance_method для создания объектов UnboundMethod. С их помощью представляется метод, ассоциированный с классом, а не с конкретным объектом. Прежде чем вызывать объект UnboundMethod, нужно связать его с каким-то объектом. Результатом операции связывания является объект Method, который можно вызывать как обычно:

umeth = String.instance_method(:length)

m1 = umeth.bind('cat')

m1.call # 3

m2 = umeth.bind('caterpillar')

m2.call # 11

Явное связывание делает объект UnboundMethod интуитивно более понятным, чем Method.

11.2.7. Как работает включение модулей?

Когда модуль включается в класс, Ruby на самом деле создает прокси-класс, являющийся непосредственным родителем данного класса. Возможно, вам это покажется интуитивно очевидным, возможно, нет. Все методы включаемого модуля «маскируются» методами, определенными в классе.

module MyMod

 def meth

  'из модуля'

 end

end

class ParentClass

 def meth

  'из родителя'

 end

end

class ChildClass < ParentClass

 include MyMod

 def meth

  'из потомка'

 end

end

x = ChildClass.new p

p x.meth # Из потомка.

Выглядит это как настоящее наследование: все, что потомок переопределил, становится действующим определением вне зависимости от того, вызывается ли include до или после переопределения.

Вот похожий пример, в котором метод потомка вызывает super, а не просто возвращает строку. Как вы думаете, что будет возвращено?

# Модуль MyMod и класс ParentClass не изменились.

class ChildClass < ParentClass

 include MyMod

 def meth

  'Из потомка: super = ' + super

 end

end

x = ChildClass.new

p x.meth # Из потомка: super = из модуля

Отсюда видно, что модуль действительно является новым родителем класса. А что если мы точно

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату