Определение методов и аргументы
Метод — это именованный, переиспользуемый кусок кода. Освоив методы, вы перестаёте копировать логику и начинаете её называть.
Суть: метод объявляется черезdef; он может принимать позиционные и ключевые аргументы, давать им значения по умолчанию и неявно возвращает значение последнего выражения — без словаreturn.
Методы — основной способ структурировать программу. Главная рубишная особенность: значение возвращается автоматически — то, что вычислила последняя строка тела, и становится результатом. Явный return нужен лишь для раннего выхода.
def square(x)
x * x # неявный возврат — return не нужен
end
puts square(5) # => 25
def greet(name, greeting = "Привет") # значение по умолчанию
"#{greeting}, #{name}!"
end
puts greet("Аня") # => Привет, Аня!
puts greet("Иван", "Здравствуй") # => Здравствуй, Иван!
Разбор: ключевые аргументы
Когда у метода много параметров, позиционные аргументы становятся загадкой: что значит true на третьем месте? Ключевые аргументы решают это — каждый параметр называется явно. Это современный рекомендуемый стиль.
def create_user(name:, role: :guest, active: true)
"#{name} (#{role}), активен: #{active}"
end
puts create_user(name: "Аня", role: :admin)
# => Аня (admin), активен: true
puts create_user(name: "Гость")
# => Гость (guest), активен: true
Как работает под капотом
Когда вы вызываете метод, Ruby ищет его в объекте-получателе и его «цепочке предков» (об этом — в разделе ООП). Аргументы связываются с параметрами по правилам: сначала позиционные по порядку, затем ключевые по именам. Метод можно вызывать на любом объекте — даже на числе, потому что число тоже объект.
square(5)
|
v
связывание: x = 5
|
v
тело: x * x --> 25
|
v
неявный возврат последнего выражения --> 25
greet("Аня")
|
name = "Аня", greeting = "Привет" (дефолт)
Та же логика «функция с дефолтами и именованными аргументами» на Python:
# Та же логика на Python ▶
def create_user(name, role="guest", active=True):
return f"{name} ({role}), активен: {active}"
print(create_user("Аня", role="admin"))
# Аня (admin), активен: True
Частые ошибки
- Лишний return. Писать
return x * xв конце метода — не ошибка, но не по-рубишному. Последнее выражение возвращается само. - Путать позиционные и ключевые. Если параметр объявлен как
name:, вызывать нужноname: "Аня", а не просто"Аня". - Изменяемый объект как дефолт. Дефолт вычисляется при каждом вызове, так что в Ruby это менее опасно, чем в Python, но всё равно держите дефолты простыми.
Best practices
- Когда параметров больше двух — переходите на ключевые аргументы: вызовы становятся самодокументированными.
- Методы-предикаты (возвращающие true/false) называйте с
?:valid?,empty?. - Держите методы короткими — один метод, одна задача. Если метод не помещается на экран, его пора разбить.
Глубже: splat-операторы и гибкость аргументов
Система аргументов в Ruby гибче, чем кажется на первый взгляд, и стоит хотя бы узнать о её возможностях. Оператор-звёздочка *args собирает произвольное число позиционных аргументов в массив — так пишут методы, принимающие сколько угодно значений. Двойная звёздочка **opts делает то же самое с ключевыми аргументами, складывая их в хэш. Есть и оператор для блока — &block, который ловит переданный блок в переменную (об этом подробнее в теме блоков). Комбинируя их, можно написать «прозрачную обёртку», которая принимает любые аргументы и передаёт их дальше нетронутыми — для этого в современном Ruby есть даже специальный оператор «передать всё» (...). Знать эти инструменты на старте необязательно, но полезно понимать: когда вы видите в чужом коде * и ** в сигнатуре метода — это не магия, а способ принимать переменное число аргументов. По мере роста ваших программ вы сами начнёте к ним тянуться, особенно когда будете писать методы, оборачивающие другие методы.
Итог. Методы объявляются через def и неявно возвращают последнее выражение. Ключевые аргументы делают вызовы читаемыми и являются современным стандартом, а имя с ? сигнализирует о предикате.