Я возьму их по одному. полностью уберите method_missing
из этого, так как это только сбивает с толку происходящее. На самом деле это совершенно не связано с этим.
Знак *
делает 2 вещи. В аргументах метода definition он собирает несколько аргументов в массив. При использовании в методе invocation массив разбивается на отдельные аргументы. Использование обоих позволяет вам пересылать любое количество аргументов другому методу.
def foo(*args)
bar(*args)
end
def bar(a, b, c)
puts a
puts b
puts c
end
foo(1,2,3) # prints 1, 2 and then 3
Поскольку вы в основном пересылаете все аргументы, это тот же шаблон.
&
для аргумента блока. Их может быть ровно один на вызов метода, это блок, который висит на конце. Это особый аргумент, поскольку он не входит в аргументы напрямую. Вы можете записать блок в переменную, зафиксировав add &someblock
в качестве последнего аргумента в определении метода.
Затем вы можете передать блок в вызове метода, используя тот же синтаксис.
def foo(&block)
bar(&block)
end
def bar
yield
end
foo { puts 'hello' } # prints hello
Это позволяет передать висячий блок другому методу, не вызывая его. Это не всегда требуется, потому что обычно вы просто используете yield
для выполнения любого переданного блока. Но если вы хотите сделать что-то помимо простого выполнения, вам нужно зафиксировать ссылку на сам блок.
Итак, если вы объедините эти две вещи, вы получите окончательный переадресатор методов. Вы захватываете все любое количество аргументов и любой блок, который висит на конце, и отправляете их другому методу.
# forwards everything to the method `bar`
def foo(*args, &block)
bar(*args, &block)
end
Наконец, send
— это просто метод. Он ожидает имя метода, за которым следует любое количество аргументов (не массив), и может опционально обрабатывать висячий блок.
Другими словами:
foo.send methodName, *args, &block
person
Alex Wayne
schedule
27.12.2012