Ruby Language
методы
Поиск…
Вступление
Функции в Ruby предоставляют организованный, многоразовый код для предварительной последовательности действий. Функции упрощают процесс кодирования, предотвращают избыточную логику и упрощают выполнение кода. В этом разделе описывается декларация и использование функций, аргументов, параметров, операторов вывода и области действия в Ruby.
замечания
Метод - это именованный блок кода, связанный с одним или несколькими объектами и обычно идентифицируемый списком параметров в дополнение к имени.
def hello(name)
"Hello, #{name}"
end
Вызов метода указывает имя метода, объект, на который он должен быть вызван (иногда называемый получателем), и ноль или более значений аргумента, назначенных параметрам именованного метода. Значение последнего выражения, оцененного в методе, становится значением выражения вызова метода.
hello("World")
# => "Hello, World"
Когда приемник не является явным, он self
.
self
# => main
self.hello("World")
# => "Hello, World"
Как объясняется в книге языка программирования Ruby , многие языки различают функции, которые не имеют связанного с ними объекта, и методы, которые вызывают на объекте получателя. Поскольку Ruby является чисто объектно-ориентированным языком, все методы являются истинными методами и связаны с хотя бы одним объектом.
Обзор параметров метода
Тип | Подпись метода | Пример вызова | Назначения |
---|---|---|---|
R equired | def fn(a,b,c) | fn(2,3,5) | a=2, b=3, c=5 |
V ariadic | def fn(*rest) | fn(2,3,5) | rest=[2, 3, 5] |
D efault | def fn(a=0,b=1) | fn(2,3) | a=2, b=3 |
K eyword | def fn(a:0,b:1) | fn(a:2,b:3) | a=2, b=3 |
Эти типы аргументов можно комбинировать практически так, как вы можете себе представить, для создания вариативных функций. Минимальное количество аргументов функции будет равно количеству необходимых аргументов в сигнатуре. Дополнительные аргументы сначала будут назначены параметрам по умолчанию, а затем - параметру *rest
.
Тип | Подпись метода | Пример вызова | Назначения |
---|---|---|---|
R, D, В, Р | def fn(a,b=1,*mid,z) | fn(2,97) | a=2, b=1, mid=[], z=97 |
fn(2,3,97) | a=2, b=3, mid=[], z=97 | ||
fn(2,3,5,97) | a=2, b=3, mid=[5], z=97 | ||
fn(2,3,5,7,97) | a=2, b=3, mid=[5,7], z=97 | ||
R, K, K | def fn(a,g:6,h:7) | fn(2) | a=2, g=6, h=7 |
fn(2,h:19) | a=2, g=6, h=19 | ||
fn(2,g:17,h:19) | a=2, g=17, h=19 | ||
В.К. | def fn(**ks) | fn(a:2,g:17,h:19) | ks={a:2, g:17, h:19} |
fn(four:4,five:5) | ks={four:4, five:5} |
Единый требуемый параметр
def say_hello_to(name)
puts "Hello #{name}"
end
say_hello_to('Charles') # Hello Charles
Несколько требуемых параметров
def greet(greeting, name)
puts "#{greeting} #{name}"
end
greet('Hi', 'Sophie') # Hi Sophie
Параметры по умолчанию
def make_animal_sound(sound = 'Cuack')
puts sound
end
make_animal_sound('Mooo') # Mooo
make_animal_sound # Cuack
Можно включить значения по умолчанию для нескольких аргументов:
def make_animal_sound(sound = 'Cuack', volume = 11)
play_sound(sound, volume)
end
make_animal_sound('Mooo') # Spinal Tap cow
Тем не менее, невозможно поставить второй, не поставляя первый. Вместо использования позиционных параметров попробуйте параметры ключевых слов:
def make_animal_sound(sound: 'Cuack', volume: 11)
play_sound(sound, volume)
end
make_animal_sound(volume: 1) # Duck whisper
Или хеш-параметр, в котором хранятся параметры:
def make_animal_sound(options = {})
options[:sound] ||= 'Cuak'
options[:volume] ||= 11
play_sound(sound, volume)
end
make_animal_sound(:sound => 'Mooo')
Значения параметров по умолчанию могут быть заданы любым выражением ruby. Выражение будет выполняться в контексте метода, поэтому вы можете даже объявить локальные переменные здесь. Обратите внимание, что вы не сможете пройти проверку кода. Предоставлено caius для указания этого .
def make_animal_sound( sound = ( raise 'TUU-too-TUU-too...' ) ); p sound; end
make_animal_sound 'blaaaa' # => 'blaaaa'
make_animal_sound # => TUU-too-TUU-too... (RuntimeError)
Необязательный параметр (ы) (оператор splat)
def welcome_guests(*guests)
guests.each { |guest| puts "Welcome #{guest}!" }
end
welcome_guests('Tom') # Welcome Tom!
welcome_guests('Rob', 'Sally', 'Lucas') # Welcome Rob!
# Welcome Sally!
# Welcome Lucas!
Обратите внимание, что welcome_guests(['Rob', 'Sally', 'Lucas'])
выводит Welcome ["Rob", "Sally", "Lucas"]!
Вместо этого, если у вас есть список, вы можете делать welcome_guests(*['Rob', 'Sally', 'Lucas'])
и это будет работать как welcome_guests('Rob', 'Sally', 'Lucas')
.
Требуемый необязательный параметр параметров
def my_mix(name,valid=true, *opt)
puts name
puts valid
puts opt
end
Вызовите следующее:
my_mix('me')
# 'me'
# true
# []
my_mix('me', false)
# 'me'
# false
# []
my_mix('me', true, 5, 7)
# 'me'
# true
# [5,7]
Определения метода - это выражения
Определение метода в Ruby 2.x возвращает символ, обозначающий имя:
class Example
puts def hello
end
end
#=> :hello
Это позволяет использовать интересные методы метапрограммирования. Например, методы могут быть обернуты другими способами:
class Class
def logged(name)
original_method = instance_method(name)
define_method(name) do |*args|
puts "Calling #{name} with #{args.inspect}."
original_method.bind(self).call(*args)
puts "Completed #{name}."
end
end
end
class Meal
def initialize
@food = []
end
logged def add(item)
@food << item
end
end
meal = Meal.new
meal.add "Coffee"
# Calling add with ["Coffee"].
# Completed add.
Захват необъявленных аргументов ключевого слова (двойной знак)
Оператор **
работает аналогично оператору *
но применяется к параметрам ключевых слов.
def options(required_key:, optional_key: nil, **other_options)
other_options
end
options(required_key: 'Done!', foo: 'Foo!', bar: 'Bar!')
#> { :foo => "Foo!", :bar => "Bar!" }
В приведенном выше примере, если **other_options
не используется, будет **other_options
сообщение ArgumentError: unknown keyword: foo, bar
.
def without_double_splat(required_key:, optional_key: nil)
# do nothing
end
without_double_splat(required_key: 'Done!', foo: 'Foo!', bar: 'Bar!')
#> ArgumentError: unknown keywords: foo, bar
Это удобно, если у вас есть хэш опций, которые вы хотите передать методу, и вы не хотите фильтровать ключи.
def options(required_key:, optional_key: nil, **other_options)
other_options
end
my_hash = { required_key: true, foo: 'Foo!', bar: 'Bar!' }
options(my_hash)
#> { :foo => "Foo!", :bar => "Bar!" }
Также можно распаковать хэш с помощью оператора **
. Это позволяет вам добавлять ключевое слово непосредственно к методу в дополнение к значениям из других хэшей:
my_hash = { foo: 'Foo!', bar: 'Bar!' }
options(required_key: true, **my_hash)
#> { :foo => "Foo!", :bar => "Bar!" }
Уступка блокам
Вы можете отправить блок в свой метод, и он может вызывать этот блок несколько раз. Это может быть сделано путем отправки ргос / лямбда или , например, но проще и быстрее с yield
:
def simple(arg1,arg2)
puts "First we are here: #{arg1}"
yield
puts "Finally we are here: #{arg2}"
yield
end
simple('start','end') { puts "Now we are inside the yield" }
#> First we are here: start
#> Now we are inside the yield
#> Finally we are here: end
#> Now we are inside the yield
Обратите внимание, что { puts ... }
не находится внутри круглых скобок, он неявно приходит после. Это также означает, что мы можем иметь только один блок yield
. Мы можем передать аргументы в yield
:
def simple(arg)
puts "Before yield"
yield(arg)
puts "After yield"
end
simple('Dave') { |name| puts "My name is #{name}" }
#> Before yield
#> My name is Dave
#> After yield
С выходом мы можем легко сделать итераторы или любые функции, которые работают с другим кодом:
def countdown(num)
num.times do |i|
yield(num-i)
end
end
countdown(5) { |i| puts "Call number #{i}" }
#> Call number 5
#> Call number 4
#> Call number 3
#> Call number 2
#> Call number 1
Фактически, с yield
такие вещи, как foreach
, each
и times
, обычно реализуются в классах.
Если вы хотите узнать, был ли вам предоставлен блок или нет, используйте block_given?
:
class Employees
def names
ret = []
@employees.each do |emp|
if block_given?
yield(emp.name)
else
ret.push(emp.name)
end
end
ret
end
end
В этом примере предполагается, что класс Employees
имеет список @employees
который можно @employees
с each
чтобы получить объекты, у которых есть имена сотрудников, используя метод name
. Если задана блок, то мы будем yield
имя к блоку, в противном случае мы просто вставьте его в массив , что мы вернемся.
Корректные аргументы
Метод может принимать параметр массива и немедленно разрушать его в именованных локальных переменных. Найдено в блоге Матиаса Мейера .
def feed( amount, (animal, food) )
p "#{amount} #{animal}s chew some #{food}"
end
feed 3, [ 'rabbit', 'grass' ] # => "3 rabbits chew some grass"
Определение метода
Методы определяются с ключевым словом def
, за которым следует имя метода и необязательный список имен параметров в круглых скобках. Код Ruby между def
и end
представляет собой тело метода.
def hello(name)
"Hello, #{name}"
end
Вызов метода указывает имя метода, объект, на который он должен быть вызван (иногда называемый получателем), и ноль или более значений аргумента, назначенных параметрам именованного метода.
hello("World")
# => "Hello, World"
Когда приемник не является явным, он self
.
Имена параметров могут использоваться как переменные внутри тела метода, а значения этих именованных параметров поступают от аргументов к вызову метода.
hello("World")
# => "Hello, World"
hello("All")
# => "Hello, All"
Использовать функцию как блок
Многие функции в Ruby принимают блок как аргумент. Например:
[0, 1, 2].map {|i| i + 1}
=> [1, 2, 3]
Если у вас уже есть функция, которая делает то, что вы хотите, вы можете превратить ее в блок using &method(:fn)
:
def inc(num)
num + 1
end
[0, 1, 2].map &method(:inc)
=> [1, 2, 3]