Ruby Language
Les méthodes
Recherche…
Introduction
Les fonctions de Ruby fournissent un code organisé et réutilisable pour préparer un ensemble d'actions. Les fonctions simplifient le processus de codage, empêchent la logique redondante et facilitent le suivi du code. Cette rubrique décrit la déclaration et l'utilisation des fonctions, des arguments, des paramètres, des instructions de rendement et de la portée dans Ruby.
Remarques
Une méthode est un bloc de code nommé, associé à un ou plusieurs objets et généralement identifié par une liste de paramètres en plus du nom.
def hello(name)
"Hello, #{name}"
end
Un appel de méthode spécifie le nom de la méthode, l'objet sur lequel il doit être appelé (parfois appelé récepteur) et zéro ou plusieurs valeurs d'argument affectées aux paramètres de la méthode nommée. La valeur de la dernière expression évaluée dans la méthode devient la valeur de l'expression d'invocation de la méthode.
hello("World")
# => "Hello, World"
Lorsque le récepteur n'est pas explicite, il est self
.
self
# => main
self.hello("World")
# => "Hello, World"
Comme expliqué dans le manuel Ruby Programming Language , de nombreux langages distinguent les fonctions sans objet associé et les méthodes appelées sur un objet récepteur. Ruby étant un langage purement orienté objet, toutes les méthodes sont des méthodes vraies et sont associées à au moins un objet.
Vue d'ensemble des paramètres de la méthode
Type | Signature de méthode | Exemple d'appel | Les devoirs |
---|---|---|---|
R Évalué | 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 |
Ces types d'arguments peuvent être combinés de presque toutes les manières possibles pour créer des fonctions variadiques. Le nombre minimum d'arguments de la fonction sera égal à la quantité d'arguments requis dans la signature. Les arguments supplémentaires seront d'abord affectés aux paramètres par défaut, puis au paramètre *rest
.
Type | Signature de méthode | Exemple d'appel | Les devoirs |
---|---|---|---|
R, D, V, R | 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 | ||
VK | 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} |
Paramètre unique requis
def say_hello_to(name)
puts "Hello #{name}"
end
say_hello_to('Charles') # Hello Charles
Plusieurs paramètres requis
def greet(greeting, name)
puts "#{greeting} #{name}"
end
greet('Hi', 'Sophie') # Hi Sophie
Paramètres par défaut
def make_animal_sound(sound = 'Cuack')
puts sound
end
make_animal_sound('Mooo') # Mooo
make_animal_sound # Cuack
Il est possible d'inclure des valeurs par défaut pour plusieurs arguments:
def make_animal_sound(sound = 'Cuack', volume = 11)
play_sound(sound, volume)
end
make_animal_sound('Mooo') # Spinal Tap cow
Cependant, il n'est pas possible de fournir le second sans fournir le premier. Au lieu d'utiliser des paramètres de position, essayez les paramètres de mot clé:
def make_animal_sound(sound: 'Cuack', volume: 11)
play_sound(sound, volume)
end
make_animal_sound(volume: 1) # Duck whisper
Ou un paramètre de hachage qui stocke les options:
def make_animal_sound(options = {})
options[:sound] ||= 'Cuak'
options[:volume] ||= 11
play_sound(sound, volume)
end
make_animal_sound(:sound => 'Mooo')
Les valeurs de paramètres par défaut peuvent être définies par n'importe quelle expression ruby. L'expression s'exécutera dans le contexte de la méthode, vous pouvez même déclarer des variables locales ici. Notez que vous ne passerez pas en revue les codes. Gracieuseté de caius pour l' avoir signalé .
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)
Paramètre (s) facultatif (opérateur 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!
Notez que welcome_guests(['Rob', 'Sally', 'Lucas'])
affichera Welcome ["Rob", "Sally", "Lucas"]!
Au lieu de cela, si vous avez une liste, vous pouvez faire welcome_guests(*['Rob', 'Sally', 'Lucas'])
et cela fonctionnera comme welcome_guests('Rob', 'Sally', 'Lucas')
.
Mélange de paramètres facultatif par défaut requis
def my_mix(name,valid=true, *opt)
puts name
puts valid
puts opt
end
Appelez comme suit:
my_mix('me')
# 'me'
# true
# []
my_mix('me', false)
# 'me'
# false
# []
my_mix('me', true, 5, 7)
# 'me'
# true
# [5,7]
Les définitions de méthode sont des expressions
Définir une méthode dans Ruby 2.x renvoie un symbole représentant le nom:
class Example
puts def hello
end
end
#=> :hello
Cela permet des techniques de métaprogrammation intéressantes. Par exemple, les méthodes peuvent être encapsulées par d'autres méthodes:
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.
Capture d'arguments de mots clés non déclarés (double splat)
L'opérateur **
fonctionne de la même manière que l'opérateur *
mais il s'applique aux paramètres de mot-clé.
def options(required_key:, optional_key: nil, **other_options)
other_options
end
options(required_key: 'Done!', foo: 'Foo!', bar: 'Bar!')
#> { :foo => "Foo!", :bar => "Bar!" }
Dans l'exemple ci-dessus, si **other_options
n'est pas utilisé, un ArgumentError: unknown keyword: foo, bar
erreur de ArgumentError: unknown keyword: foo, bar
serait **other_options
.
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
C'est pratique lorsque vous avez un hachage d'options que vous souhaitez transmettre à une méthode et que vous ne souhaitez pas filtrer les clés.
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!" }
Il est également possible de déballer un hash en utilisant l'opérateur **
. Cela vous permet de fournir un mot-clé directement à une méthode en plus des valeurs d'autres hachages:
my_hash = { foo: 'Foo!', bar: 'Bar!' }
options(required_key: true, **my_hash)
#> { :foo => "Foo!", :bar => "Bar!" }
Céder aux blocs
Vous pouvez envoyer un bloc à votre méthode et il peut appeler ce bloc plusieurs fois. Cela peut être fait en envoyant un proc / lambda ou autre, mais c'est plus facile et plus rapide avec le 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
Notez que le { puts ... }
n'est pas entre parenthèses, il vient implicitement après. Cela signifie également que nous ne pouvons avoir qu'un seul bloc de yield
. Nous pouvons transmettre des arguments au 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
Avec le rendement, nous pouvons facilement créer des itérateurs ou des fonctions fonctionnant sur d'autres codes:
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
En fait, c'est avec le yield
que des choses comme foreach
, each
et les times
sont généralement implémentées dans les classes.
Si vous voulez savoir si un bloc vous a été donné ou non, utilisez 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
Cet exemple suppose que la classe Employees
possède une liste @employees
pouvant être itérée avec each
pour obtenir des objets ayant des noms d'employés à l'aide de la méthode name
. Si on nous donne un bloc, alors nous yield
le nom au bloc, sinon nous le pousserons simplement dans un tableau que nous renverrons.
Tuple Arguments
Une méthode peut prendre un paramètre de tableau et le déstructurer immédiatement en variables locales nommées. Trouvé sur le blog de Mathias Meyer .
def feed( amount, (animal, food) )
p "#{amount} #{animal}s chew some #{food}"
end
feed 3, [ 'rabbit', 'grass' ] # => "3 rabbits chew some grass"
Définir une méthode
Les méthodes sont définies avec le mot-clé def
, suivi du nom de la méthode et d'une liste facultative de noms de paramètre entre parenthèses. Le code Ruby entre def
et end
représente le corps de la méthode.
def hello(name)
"Hello, #{name}"
end
Un appel de méthode spécifie le nom de la méthode, l'objet sur lequel il doit être appelé (parfois appelé récepteur) et zéro ou plusieurs valeurs d'argument affectées aux paramètres de la méthode nommée.
hello("World")
# => "Hello, World"
Lorsque le récepteur n'est pas explicite, il est self
.
Les noms de paramètre peuvent être utilisés comme variables dans le corps de la méthode et les valeurs de ces paramètres nommés proviennent des arguments d'une invocation de méthode.
hello("World")
# => "Hello, World"
hello("All")
# => "Hello, All"
Utiliser une fonction comme un bloc
De nombreuses fonctions de Ruby acceptent un bloc comme argument. Par exemple:
[0, 1, 2].map {|i| i + 1}
=> [1, 2, 3]
Si vous avez déjà une fonction qui fait ce que vous voulez, vous pouvez la transformer en un bloc en utilisant &method(:fn)
:
def inc(num)
num + 1
end
[0, 1, 2].map &method(:inc)
=> [1, 2, 3]