Методы, наряду с переменными и операторами, являются основными строительными блоками в Ruby. Мы уже применяли методы, определенные для таких классов, как числа и строки.
При написании программ часто приходится создавать дополнительные методы (называемые также функциями или подпрограммами). Каждый метод должен быть определен до своего использования с помощью ключевых слов def и end. Как уже отмечалось, имя метода должно начинаться со строчной латинской буквы (от a до z). Также как и переменным, методам рекомендуется давать осмысленные ("говорящие") имена. Если имя состоит из нескольких слов, то для их разделения рекомендуется использовать символ подчеркивания, либо каждое слово, начиная со второго, выделять заглавной буквой.
Методам, определяемым вне определения класса, присваивается специальная пометка private (частный), называемая спецификатором доступа. При обращении к такому методу используется функциональная форма вызова метода, а не оператор вызова метода . (точка). С другой стороны методы, определенные внутри определения класса, по умолчанию помечаются как public. При вызове методов, определенных таким образом, используется "точечная" форма вызова метода. Так как мы пока не создаем новых классов в своих программах, то все методы, разработанные нами, будут вызываться только в функциональном стиле.
Давайте перепишем нашу первую программу так, чтобы она использовала вызов метода. Для этого в файл с именем method.rb поместим следующий текст:
def helloWorld puts "Hello, World!" end helloWorldЧасть программы между словами def и end (в нашем случае единственный оператор puts) составляет тело метода.
Изменим метод так, чтобы он мог печатать любой текст:
def saySomething(text) puts text end saySomething("Hello, World!")Мы добавили параметр text в наш метод. При определении метода параметры всегда заключаются в круглые скобки, следующие сразу за именем метода, и разделяются запятыми.
Параметры метода являются локальными переменными. Это означает (в терминах наших наклеек и объектов), что метод оперирует копиями переменных, переданных ему (часто говорят, что параметры передаются по значению). Другими словами, перед тем как передать метки и создать метод, Ruby создает копии всех этих объектов, временно, только на время выполнения метода, помещает имена параметров на них. Проиллюстрируем это следующим примером:
def printOneMoreThan(x) x += 1 puts "Во время выполнения: #{x}" end x = 1 puts "До: #{x}" printOneMoreThan(x) puts "После: #{x}"Выполним эту программу и убедимся, что значение переменной x не изменилось после завершения метода printOneMoreThan.
При создании метода Ruby позволяет задать значения некоторых аргументов. Эти, так называемые параметры по умолчанию, дают возможность вызова без обязательного указания значения всех параметров. Ниже приводится пример такого метода.
def saySomething(text = 'Hello, World!') puts text end saySomethingПри этом вызове метода параметр не указывался. Ruby позволяет вызвать метод несколькими различными способами:
saySomething saySomething() saySomething "Пробел между именем метода и аргументами" saySomething(" или использование скобок")Рекомендуется всегда заключать аргументы метода в круглые скобки. Это позволит избежать некоторых ошибок и недоразумений. Общепринятыми исключениями являются методы печати - puts, print и т. д., хотя и при их вызове аргументы также можно заключать в скобки:
puts(2 + 3) print("Hello, ", 3 + 4, "\n")
Значениями по умолчанию могут быть любые выражения Ruby. Они вычисляются в момент вызова метода, причем вычисление происходит слева направо. В этих выражениях могут использоваться и другие параметры. Следующий пример демонстрирует поведение метода в зависимости от количества аргументов при вызове:
def options(a=99, b=a+1) [a, b] end p options # [99, 100] p options(1) # [1, 2] p options(2, 4) # [2, 4]
После всех обычных аргументов в качестве аргумента может быть указан массив, что обозначается символом * перед его именем. При вызове таким образом определенного метода, Ruby подсчитывает количество переданных аргументов и, если их количество больше, чем число обычных параметров, то оставшиеся размещает в новом объекте класса Array. Например,
def varargs(a, *b) [a, b] end p varargs(1) # [1, []] p varargs(1, 2) # [1, [2]] p varargs(1, 2, 3) # [1, [2, 3]]Если аргумент- массив следует за аргументами, имеющими значения по умолчанию, то при недостатке аргументов используются значения по умолчанию, в противном случае размещение параметров аналогично предыдущему. Проиллюстрируем сказанное примером:
def mixed(a, b=99, *c) [a, b, c] end p mixed(1) # [1, 99, []] p mixed(1, 2) # [1, 2, []] p mixed(1, 2, 3) # [1, 2, [3]] p mixed(1, 2, 3, 4) # [1, 2, [3, 4]]
Очень часто от метода требуется возвращение значения, полученного в результате его выполнения. Для этого используется конструкция return выражение (если вы опустите выражение, оставив только return, то возвращаемым значением будет nil). Если не использовать оператор return, то значение, возвращаемое методом, будет значением последнего выражения, вычисленного в методе.
Остановимся несколько подробнее на последнем утверждении. Дело в том, что в Ruby, в отличии от многих других языков программирования, любое выражение имеет значение. Приведем фрагмент программы для иллюстрации этого факта:
def saySomething(text = 'Hello, World!') puts text end x = saySomething puts x puts x = 23 puts x += 1Обратите внимание, что значение, возвращаемое методом saySomething, есть nil. Это означает, что значение последнего утверждения в методе (т. е. оператора puts text) было nil. Значение, возвращаемое оператором x = 23 есть число 23, а оператором x += 1 равно 24. Теперь попробуйте догадаться, каков будет результат выполнения программы:
def countUp(x = 0) puts "В этот момент X равно #{x}" x += 1 end
x = countUp() x = countUp(x) x = countUp(x)
Задания