Ruby Language
methoden
Zoeken…
Invoering
Functies in Ruby bieden georganiseerde, herbruikbare code om een reeks acties uit te voeren. Functies vereenvoudigen het coderingsproces, voorkomen overbodige logica en maken code eenvoudiger te volgen. Dit onderwerp beschrijft de verklaring en het gebruik van functies, argumenten, parameters, opbrengstverklaringen en bereik in Ruby.
Opmerkingen
Een methode is een benoemd codeblok, gekoppeld aan een of meer objecten en meestal geïdentificeerd door een lijst met parameters naast de naam.
def hello(name)
"Hello, #{name}"
end
Een methode-aanroep specificeert de methode-naam, het object waarop deze moet worden aangeroepen (soms de ontvanger genoemd) en nul of meer argumentwaarden die zijn toegewezen aan de genoemde methode-parameters. De waarde van de laatste uitdrukking die in de methode is geëvalueerd, wordt de waarde van de methode-aanroepingsexpressie.
hello("World")
# => "Hello, World"
Wanneer de ontvanger niet expliciet is, is hij self
.
self
# => main
self.hello("World")
# => "Hello, World"
Zoals uitgelegd in het Ruby Programming Language- boek, maken veel talen onderscheid tussen functies, waaraan geen object is gekoppeld, en methoden die op een ontvangerobject worden aangeroepen. Omdat Ruby een puur objectgeoriënteerde taal is, zijn alle methoden echte methoden en worden ze geassocieerd met ten minste één object.
Overzicht van methodeparameters
Type | Methode handtekening | Oproepvoorbeeld | opdrachten |
---|---|---|---|
R gelijkgesteld | def fn(a,b,c) | fn(2,3,5) | a=2, b=3, c=5 |
V ariadisch | 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 oogwoord | def fn(a:0,b:1) | fn(a:2,b:3) | a=2, b=3 |
Deze argumenttypen kunnen op vrijwel elke manier worden gecombineerd om variadische functies te maken. Het minimumaantal argumenten voor de functie is gelijk aan het aantal vereiste argumenten in de handtekening. Extra argumenten worden eerst toegewezen aan standaardparameters en vervolgens aan de parameter *rest
.
Type | Methode handtekening | Oproepvoorbeeld | opdrachten |
---|---|---|---|
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} |
Enkele vereiste parameter
def say_hello_to(name)
puts "Hello #{name}"
end
say_hello_to('Charles') # Hello Charles
Meerdere vereiste parameters
def greet(greeting, name)
puts "#{greeting} #{name}"
end
greet('Hi', 'Sophie') # Hi Sophie
Standaard parameters
def make_animal_sound(sound = 'Cuack')
puts sound
end
make_animal_sound('Mooo') # Mooo
make_animal_sound # Cuack
Het is mogelijk om standaardwaarden op te nemen voor meerdere argumenten:
def make_animal_sound(sound = 'Cuack', volume = 11)
play_sound(sound, volume)
end
make_animal_sound('Mooo') # Spinal Tap cow
Het is echter niet mogelijk om de tweede te leveren zonder ook de eerste te leveren. Probeer in plaats van positionele parameters te gebruiken, trefwoordparameters:
def make_animal_sound(sound: 'Cuack', volume: 11)
play_sound(sound, volume)
end
make_animal_sound(volume: 1) # Duck whisper
Of een hash-parameter die opties opslaat:
def make_animal_sound(options = {})
options[:sound] ||= 'Cuak'
options[:volume] ||= 11
play_sound(sound, volume)
end
make_animal_sound(:sound => 'Mooo')
Standaard parameterwaarden kunnen worden ingesteld met elke robijnrode uitdrukking. De uitdrukking wordt uitgevoerd in de context van de methode, dus u kunt hier zelfs lokale variabelen opgeven. Let op, komt niet door code review. Met dank aan Caius voor het wijzen hierop .
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)
Optionele parameter (s) (splat-operator)
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!
Merk op dat welcome_guests(['Rob', 'Sally', 'Lucas'])
Welcome ["Rob", "Sally", "Lucas"]!
In plaats daarvan, als je een lijst hebt, kun je welcome_guests(*['Rob', 'Sally', 'Lucas'])
doen welcome_guests(*['Rob', 'Sally', 'Lucas'])
en dat zal werken als welcome_guests('Rob', 'Sally', 'Lucas')
.
Vereiste standaard optionele parameter mix
def my_mix(name,valid=true, *opt)
puts name
puts valid
puts opt
end
Bel als volgt:
my_mix('me')
# 'me'
# true
# []
my_mix('me', false)
# 'me'
# false
# []
my_mix('me', true, 5, 7)
# 'me'
# true
# [5,7]
Methodedefinities zijn uitdrukkingen
Als u een methode definieert in Ruby 2.x, wordt een symbool geretourneerd dat de naam vertegenwoordigt:
class Example
puts def hello
end
end
#=> :hello
Dit maakt interessante metaprogrammeringstechnieken mogelijk. Methoden kunnen bijvoorbeeld op andere manieren worden ingepakt:
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.
Niet-aangegeven trefwoordargumenten vastleggen (dubbele splat)
De **
operator werkt op dezelfde manier als de *
operator maar is van toepassing op trefwoordparameters.
def options(required_key:, optional_key: nil, **other_options)
other_options
end
options(required_key: 'Done!', foo: 'Foo!', bar: 'Bar!')
#> { :foo => "Foo!", :bar => "Bar!" }
In het bovenstaande voorbeeld, als de **other_options
niet wordt gebruikt, zou een ArgumentError: unknown keyword: foo, bar
**other_options
worden opgeworpen.
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
Dit is handig als u een aantal opties hebt die u aan een methode wilt doorgeven en u de toetsen niet wilt filteren.
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!" }
Het is ook mogelijk om een hash uit te pakken met de **
operator. Hiermee kunt u trefwoorden direct aan een methode toevoegen naast waarden uit andere hashes:
my_hash = { foo: 'Foo!', bar: 'Bar!' }
options(required_key: true, **my_hash)
#> { :foo => "Foo!", :bar => "Bar!" }
Opbrengst aan blokken
U kunt een blok naar uw methode verzenden en het kan dat blok meerdere keren aanroepen. Dit kan worden gedaan door een proc / lambda of iets dergelijks te sturen, maar is gemakkelijker en sneller met 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
Merk op dat de { puts ... }
niet tussen haakjes staat, maar impliciet volgt. Dit betekent ook dat we slechts één yield
kunnen hebben. We kunnen argumenten doorgeven aan de 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
Met opbrengst kunnen we gemakkelijk iterators maken of andere functies die op andere code werken:
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
In feite is het met yield
dat dingen als foreach
each
times
in het algemeen in klassen worden geïmplementeerd.
Als je wilt weten of je een blok hebt gekregen of niet, gebruik dan 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
In dit voorbeeld wordt ervan uitgegaan dat de klasse Employees
een @employees
die met each
kan worden herhaald om objecten met de name
werknemer op te halen. Als we een blok krijgen, dan zullen we yield
de naam het blok, anders duwen we gewoon aan een array die we terugkeren.
Tuple Argumenten
Een methode kan een matrixparameter nemen en deze onmiddellijk in benoemde lokale variabelen vernietigen. Gevonden op het blog van Mathias Meyer .
def feed( amount, (animal, food) )
p "#{amount} #{animal}s chew some #{food}"
end
feed 3, [ 'rabbit', 'grass' ] # => "3 rabbits chew some grass"
Een methode definiëren
Methoden worden gedefinieerd met het sleutelwoord def
, gevolgd door de methode naam en een optionele lijst met parameternamen tussen haakjes. De Ruby-code tussen def
en end
vertegenwoordigt de body van de methode.
def hello(name)
"Hello, #{name}"
end
Een methode-aanroep specificeert de methode-naam, het object waarop deze moet worden aangeroepen (soms de ontvanger genoemd) en nul of meer argumentwaarden die zijn toegewezen aan de genoemde methode-parameters.
hello("World")
# => "Hello, World"
Wanneer de ontvanger niet expliciet is, is hij self
.
Parameternamen kunnen worden gebruikt als variabelen in de methode en de waarden van deze benoemde parameters komen uit de argumenten voor een methode-aanroep.
hello("World")
# => "Hello, World"
hello("All")
# => "Hello, All"
Gebruik een functie als blok
Veel functies in Ruby accepteren een blok als argument. bv:
[0, 1, 2].map {|i| i + 1}
=> [1, 2, 3]
Als je al een functie hebt die doet wat je wilt, kun je deze met behulp van &method(:fn)
in een blok veranderen:
def inc(num)
num + 1
end
[0, 1, 2].map &method(:inc)
=> [1, 2, 3]