Вызов методов
Вызов метода отправляет сообщение объекту, чтобы он выполнил некоторую работу.
В Ruby вы отправляете сообщение объекту так:
my_method()
Обратите внимание, что круглые скобки необязательны:
my_method
За исключением случаев, когда использование и опускание скобок различаются, в этом документе используются скобки, когда присутствуют аргументы, чтобы избежать путаницы.
Этот раздел охватывает только вызов методов. См. также документацию синтаксиса по определению методов.
Получатель
self является получателем по умолчанию. Если вы не укажете получателя, будет использован self. Чтобы указать получателя, используйте ..
my_object.my_method
Это отправляет сообщение my_method объекту my_object. Любой объект может быть получателем, но в зависимости от видимости метода отправка сообщения может вызвать NoMethodError.
Вы также можете использовать :: для обозначения получателя, но это редко используется из-за потенциальной путаницы с :: для пространств имен.
Аргументы
Существует три типа аргументов при отправке сообщения: позиционные аргументы, ключевые (или именованные) аргументы и аргумент блока. Каждое отправленное сообщение может использовать один, два или все типы аргументов, но аргументы должны быть предоставлены в этом порядке.
Все аргументы в Ruby передаются по ссылке и не вычисляются лениво.
Каждый аргумент разделяется ,.
my_method(1, '2', :three)
Аргументы могут быть выражением, аргументом типа хэш:
'key' => value
или ключевым аргументом:
key: value
Хэш и ключевые аргументы должны быть смежными и должны появляться после всех позиционных аргументов, но могут быть смешаны:
my_method('a' => 1, b: 2, 'c' => 3)
Позиционные аргументы
Позиционные аргументы для сообщения следуют за именем метода:
my_method(argument1, argument2)
Во многих случаях круглые скобки не нужны при отправке сообщения:
my_method argument1, argument2
Однако, скобки необходимы, чтобы избежать неоднозначности. Это вызовет SyntaxError, потому что Ruby не знает, какой аргумент метода argument3 должен быть отправлен:
method_one argument1, method_two argument2, argument3
Если определение метода имеет *argument, дополнительные позиционные аргументы будут присвоены argument в методе как массив.
Если определение метода не включает ключевые аргументы, ключевые или аргументы типа хэш присваиваются как единственный хэш последнему аргументу:
def my_method(options)
p options
end
my_method('a' => 1, b: 2) # prints: {'a'=>1, :b=>2}
Если предоставлено слишком много позиционных аргументов, будет поднято исключение ArgumentError.
Позиционные аргументы по умолчанию
Когда метод определяет аргументы по умолчанию, вам не нужно предоставлять все аргументы методу. Ruby заполнит недостающие аргументы в порядке.
Сначала рассмотрим простой случай, когда аргументы по умолчанию появляются справа. Рассмотрим этот метод:
def my_method(a, b, c = 3, d = 4) p [a, b, c, d] end
Здесь c и d имеют значения по умолчанию, которые Ruby применит для вас. Если вы передадите только два аргумента этому методу:
my_method(1, 2)
Вы увидите, что Ruby выведет [1, 2, 3, 4].
Если вы передадите три аргумента:
my_method(1, 2, 5)
Вы увидите, что Ruby выведет [1, 2, 5, 4].
Ruby заполняет недостающие аргументы слева направо.
Ruby позволяет значениям по умолчанию появляться посередине позиционных аргументов. Рассмотрим этот более сложный метод:
def my_method(a, b = 2, c = 3, d) p [a, b, c, d] end
Здесь b и c имеют значения по умолчанию. Если вы передадите только два аргумента этому методу:
my_method(1, 4)
Вы увидите, что Ruby выведет [1, 2, 3, 4].
Если вы передадите три аргумента:
my_method(1, 5, 6)
Вы увидите, что Ruby выведет [1, 5, 3, 6].
Описание этого словами становится сложным и запутанным. Я опишу это в переменных и значениях вместо этого.
Сначала 1 присваивается a, затем 6 присваивается d. Это оставляет только аргументы со значениями по умолчанию. Поскольку 5 еще не присвоено, оно предоставляется b, а c использует значение по умолчанию 3.
Ключевые аргументы
Ключевые аргументы следуют за позиционными аргументами и разделяются запятыми, как и позиционные аргументы:
my_method(positional1, keyword1: value1, keyword2: value2)
Любые ключевые аргументы, которые не указаны, будут использовать значение по умолчанию из определения метода. Если ключевой аргумент предоставлен, которого не было в списке метода, будет поднято исключение ArgumentError.
Аргумент блока
Аргумент блока отправляет замыкание из области вызова в метод.
Аргумент блока всегда находится последним при отправке сообщения методу. Блок отправляется в метод, используя do ... end или { ...
}:
my_method do # ... end
или:
my_method {
# ...
}
do end имеет более низкий приоритет, чем { }, поэтому:
method_1 method_2 {
# ...
}
Отправляет блок в method_2, в то время как:
method_1 method_2 do # ... end
Отправляет блок в method_1. Обратите внимание, что в первом случае, если используются круглые скобки, блок отправляется в method_1.
Блок будет принимать аргументы от метода, в который он был отправлен. Аргументы определяются аналогично тому, как метод определяет аргументы. Аргументы блока идут в | ... | после открытия do или {:
my_method do |argument1, argument2| # ... end
Локальные аргументы блока
Вы также можете объявить локальные аргументы блока, используя ; в списке аргументов блока. Присвоение локальному аргументу блока не переопределит локальные аргументы за пределами блока в области вызова:
def my_method
yield self
end
place = "world"
my_method do |obj; place|
place = "block"
puts "hello #{obj} this is #{place}"
end
puts "place is: #{place}"
Это выводит:
hello main this is block place is world
Таким образом, переменная place в блоке не является той же переменной place, что и вне блока. Удаление ;
place из аргументов блока дает такой результат:
hello main this is block place is block
Преобразование массива в аргументы
Учитывая следующий метод:
def my_method(argument1, argument2, argument3) end
Вы можете преобразовать массив в список аргументов с помощью оператора * (или splat):
arguments = [1, 2, 3] my_method(*arguments)
или:
arguments = [2, 3] my_method(1, *arguments)
Оба эквивалентны:
my_method(1, 2, 3)
Если метод принимает ключевые аргументы, оператор splat преобразует хэш в конце массива в ключевые аргументы:
def my_method(a, b, c: 3)
end
arguments = [1, 2, { c: 4 }]
my_method(*arguments)
Вы также можете использовать оператор ** (описанный ниже) для преобразования хэша в ключевые аргументы.
Если количество объектов в массиве не соответствует количеству аргументов метода, будет поднято исключение ArgumentError.
Если оператор splat стоит первым в вызове, круглые скобки должны быть использованы, чтобы избежать предупреждения.
Преобразование хэша в ключевые аргументы
Учитывая следующий метод:
def my_method(first: 1, second: 2, third: 3) end
Вы можете преобразовать хэш в ключевые аргументы с помощью оператора **:
arguments = { first: 3, second: 4, third: 5 }
my_method(**arguments)
или:
arguments = { first: 3, second: 4 }
my_method(third: 5, **arguments)
Оба эквивалентны:
my_method(first: 3, second: 4, third: 5)
Если в определении метода используется ** для сбора произвольных ключевых аргументов, они не будут собраны оператором *:
def my_method(*a, **kw) p arguments: a, keywords: kw end my_method(1, 2, '3' => 4, five: 6)
Выводит:
{:arguments=>[1, 2], :keywords=>{"3"=>4, :five=>6}}
В отличие от оператора splat, описанного выше, оператор ** не имеет общепризнанного имени.
Преобразование Proc в блок
Учитывая метод, который использует блок:
def my_method yield self end
Вы можете преобразовать процедуру или лямбду в аргумент блока с помощью оператора &:
argument = proc { |a| puts "#{a.inspect} was yielded" }
my_method(&argument)
Если оператор splat стоит первым в вызове, круглые скобки должны быть использованы, чтобы избежать предупреждения.
В отличие от оператора splat, описанного выше, оператор & не имеет общепризнанного имени.
Поиск метода
Когда вы отправляете сообщение, Ruby ищет метод, соответствующий имени сообщения для получателя. Методы хранятся в классах и модулях, поэтому поиск метода проходит по ним, а не по самим объектам.
Вот порядок поиска метода для класса или модуля получателя R:
-
Модули, добавленные к
Rв обратном порядке -
Соответствующий метод в
R -
Модули, включённые в
Rв обратном порядке
Если R — класс с суперклассом, это повторяется для суперкласса R до тех пор, пока не будет найден метод.
После того, как совпадение найдено, поиск метода прекращается.
Если совпадение не найдено, это повторяется с начала, но ищется method_missing. По умолчанию method_missing — BasicObject#method_missing, который вызывает исключение NameError при вызове.
Если активны усовершенствования (экспериментальная функция), поиск метода меняется. См. документацию по усовершенствованиям для получения подробной информации.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.