Ruby Language
metoder
Sök…
Introduktion
Funktioner i Ruby tillhandahåller organiserad, återanvändbar kod för att förforma en uppsättning åtgärder. Funktioner förenklar kodningsprocessen, förhindrar redundant logik och gör koden lättare att följa. Det här ämnet beskriver deklarationen och användningen av funktioner, argument, parametrar, avkastningsförklaringar och omfattning i Ruby.
Anmärkningar
En metod är ett namngivet kodblock, associerat med ett eller flera objekt och generellt identifieras av en lista med parametrar utöver namnet.
def hello(name)
"Hello, #{name}"
end
En metodinkallation anger metodnamnet, objektet som det ska anropas (ibland kallat mottagaren) och noll eller fler argumentvärden som tilldelas de nämnda metodparametrarna. Värdet på det sista uttrycket som utvärderas i metoden blir värdet på metodens invokationsuttryck.
hello("World")
# => "Hello, World"
När mottagaren inte är uttrycklig är den self
.
self
# => main
self.hello("World")
# => "Hello, World"
Som förklarats i Ruby Programming Language- boken skiljer många språk mellan funktioner, som inte har något associerat objekt, och metoder, som åberopas på ett mottagarobjekt. Eftersom Ruby är ett rent objektorienterat språk är alla metoder verkliga metoder och är associerade med minst ett objekt.
Översikt över metodparametrar
Typ | Metodunderskrift | Ring exempel | Uppgifter |
---|---|---|---|
R utjämnade | def fn(a,b,c) | fn(2,3,5) | a=2, b=3, c=5 |
V ariadisk | 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 |
Dessa argumenttyper kan kombineras på nästan vilket sätt du kan tänka dig att skapa variadiska funktioner. Det minsta antalet argument för funktionen kommer att motsvara mängden nödvändiga argument i signaturen. Extra argument tilldelas först standardparametrar och sedan till *rest
viloparametern.
Typ | Metodunderskrift | Ring exempel | Uppgifter |
---|---|---|---|
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} |
Enskild parameter
def say_hello_to(name)
puts "Hello #{name}"
end
say_hello_to('Charles') # Hello Charles
Flera nödvändiga parametrar
def greet(greeting, name)
puts "#{greeting} #{name}"
end
greet('Hi', 'Sophie') # Hi Sophie
Standardparametrar
def make_animal_sound(sound = 'Cuack')
puts sound
end
make_animal_sound('Mooo') # Mooo
make_animal_sound # Cuack
Det är möjligt att inkludera standardvärden för flera argument:
def make_animal_sound(sound = 'Cuack', volume = 11)
play_sound(sound, volume)
end
make_animal_sound('Mooo') # Spinal Tap cow
Det är dock inte möjligt att leverera den andra utan att också leverera den första. Istället för att använda positionsparametrar, prova nyckelordsparametrar:
def make_animal_sound(sound: 'Cuack', volume: 11)
play_sound(sound, volume)
end
make_animal_sound(volume: 1) # Duck whisper
Eller en hash-parameter som lagrar alternativ:
def make_animal_sound(options = {})
options[:sound] ||= 'Cuak'
options[:volume] ||= 11
play_sound(sound, volume)
end
make_animal_sound(:sound => 'Mooo')
Standardparametervärden kan ställas in med valfritt rubinuttryck. Uttrycket körs i samband med metoden, så att du till och med kan deklara lokala variabler här. Observera att du inte kommer igenom kodgranskningen. Med tillstånd av caius för att påpeka detta .
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)
Valfri parameter (er) (splat-operatör)
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!
Observera att welcome_guests(['Rob', 'Sally', 'Lucas'])
kommer att producera Welcome ["Rob", "Sally", "Lucas"]!
Istället, om du har en lista, kan du göra welcome_guests(*['Rob', 'Sally', 'Lucas'])
och det fungerar som welcome_guests('Rob', 'Sally', 'Lucas')
.
Obligatorisk standardalternativmix
def my_mix(name,valid=true, *opt)
puts name
puts valid
puts opt
end
Ring enligt följande:
my_mix('me')
# 'me'
# true
# []
my_mix('me', false)
# 'me'
# false
# []
my_mix('me', true, 5, 7)
# 'me'
# true
# [5,7]
Metoddefinitioner är uttryck
Att definiera en metod i Ruby 2.x returnerar en symbol som representerar namnet:
class Example
puts def hello
end
end
#=> :hello
Detta möjliggör intressanta metaprogrammeringstekniker. Till exempel kan metoder lindas med andra metoder:
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.
Fånga odeklarerade sökordargument (dubbel splatt)
Operatören **
fungerar på samma sätt som operatören *
men det gäller sökordsparametrar.
def options(required_key:, optional_key: nil, **other_options)
other_options
end
options(required_key: 'Done!', foo: 'Foo!', bar: 'Bar!')
#> { :foo => "Foo!", :bar => "Bar!" }
I exemplet ovan, om **other_options
inte används, skulle ett ArgumentError: unknown keyword: foo, bar
stapelfel tas upp.
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
Detta är praktiskt när du har en hash med alternativ som du vill överföra till en metod och du inte vill filtrera tangenterna.
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!" }
Det är också möjligt att packa upp en hash med **
operatören. Detta gör att du kan leverera nyckelord direkt till en metod utöver värden från andra hash:
my_hash = { foo: 'Foo!', bar: 'Bar!' }
options(required_key: true, **my_hash)
#> { :foo => "Foo!", :bar => "Bar!" }
Avkastning till block
Du kan skicka ett block till din metod och det kan ringa det blocket flera gånger. Detta kan göras genom att skicka en proc / lambda eller så, men är enklare och snabbare med 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
Observera att { puts ... }
inte finns inom parenteserna, det kommer implicit efter. Det betyder också att vi bara kan ha ett yield
. Vi kan överföra argument till 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
Med avkastning kan vi enkelt göra iteratorer eller andra funktioner som fungerar med annan kod:
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
I själva verket är det med yield
som saker som foreach
, each
times
allmänhet implementeras i klasser.
Om du vill ta reda på om du har fått ett block eller inte, använd 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
Detta exempel förutsätter att Employees
klassen har en @employees
lista som kan upprepas med each
för att få objekt som har anställdas namn med hjälp av name
metoden. Om vi får ett block, kommer vi att yield
namnet till blocket, annars skjuter vi det bara till en matris som vi returnerar.
Tuple-argument
En metod kan ta en matrisparameter och förstöra den omedelbart i namngivna lokala variabler. Hittade på Mathias Meyers blogg .
def feed( amount, (animal, food) )
p "#{amount} #{animal}s chew some #{food}"
end
feed 3, [ 'rabbit', 'grass' ] # => "3 rabbits chew some grass"
Definiera en metod
Metoder definieras med def
nyckelordet, följt av metodnamnet och en valfri lista över parameternamn inom parentes. Rubinkoden mellan def
och end
representerar metodens kropp .
def hello(name)
"Hello, #{name}"
end
En metodinkallation anger metodnamnet, objektet som det ska anropas (ibland kallat mottagaren) och noll eller fler argumentvärden som tilldelas de nämnda metodparametrarna.
hello("World")
# => "Hello, World"
När mottagaren inte är uttrycklig är den self
.
Parameternamn kan användas som variabler i metodkroppen, och värdena på dessa namngivna parametrar kommer från argumenten till en metodkallning.
hello("World")
# => "Hello, World"
hello("All")
# => "Hello, All"
Använd en funktion som ett block
Många funktioner i Ruby accepterar ett block som ett argument. T.ex:
[0, 1, 2].map {|i| i + 1}
=> [1, 2, 3]
Om du redan har en funktion som gör vad du vill kan du förvandla den till ett block med &method(:fn)
:
def inc(num)
num + 1
end
[0, 1, 2].map &method(:inc)
=> [1, 2, 3]