Die Programmiersprache Ruby

Blog| Forum| Wiki  

Eine Methode oder Funktion beschreibt im Grunde ein Bündel von Ausdrücken, also Codezeilen, die immer wieder ausgeführt werden können, ohne noch einmal getippt werden zu müssen. Sie werden mit dem Schlüsselwort def erstellt und können sehr komplex werden. Eine extrem einfach Methodendefinition sieht aber schon so aus:

1
2
3
4
5
def hallo
  puts "Hallo!"
end
#Die Methode kann dann einfach ��ber ihren Namen aufgerufen werden: 
hallo #=> Hallo!


Es gibt allerdings einige Beschränkungen in der Wahl von Methodennamen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#Keine Nicht-ASCII-Zeichen
def ������������
end
#Keine Operatoren im Namen (au��er es ist NUR ein Operator)
def a+b
end
#Keine Schl��sselw��rter
def if
end
#Keine Zahlen am Anfang
def 4t
end
#Keine Punkte (au��er im Sinne von Klassenmethoden)
def a.b
end

Inhaltsverzeichnis

Argumente

Methoden sind nicht starr; sie können Argumente oder Parameter erhalten, die ihr Verhalten beeinflussen oder einfach nur ausgewertet werden. Um einer Methode Argumente zu übergeben, schreibt man sie einfach hinter die Methodendefinition, wahlweise mit Klammern oder ohne. Diese Argumente fungieren dann als zum Methodenblock lokale Variablen, können also von außen nicht abgerufen werden und werden vom GC entfernt, sobald die Methode zu Ende ist. Eine einfache Methode, die ihr Argument auswertet, könnte so aussehen:

1
2
3
4
def plus_eins(zahl)
  puts zahl + 1
end
plus_eins(3) #=> 4


Die Klasse eines Arguments ist unwichtig; Ruby prüft Argumente nur, ob sie das können, was von ihnen verlangt wird. Dies wird im Artikel Duck Typing näher erläutert.

By reference/by value

Methodenargumente werden in Ruby by reference übergeben, außer es handelt sich um einen Immediate Value:

1
2
3
4
5
6
7
8
9
10
11
12
13
def meine_methode(arg)
  arg[0] = 10
end
ary = [0, 1]
meine_methode(ary)
p ary #=> [10, 1]
#Ein Fixnum ist ein Immediate Value: 
def plus_gleich_eins(zahl)
  zahl += 1
end
z = 3
plus_gleich_eins(zahl)
puts z #=> 3


Optionale Argumente

Manche Methoden erfordern es nicht zwingend, dass ein Argumente übergeben wird, sie enthalten optionale Argumente. Optionale Argumente müssen immer nach den verpflichtenden Argumenten definiert werden und werden nach der Syntax opt1 = def1 erstellt:

1
2
3
4
5
6
7
8
9
def mit_opts(pflicht1, opt1 = "Optionales Argument")
  puts "#{pflicht1} und #{opt1} erhalten!"
end
mit_opts
#=> ArgumentError
mit_opts("Hallo!")
#=> Hallo! und Optionales Argument erhalten!
mit_opts("Hallo", "Bye!")
#=> Hallo! und Bye! erhalten!


Benannte Argumente

Eigentlich erlaubt Ruby keine benannten Argumente, doch es gibt einen Trick, das zu umgehen: Man nimmt einfach ein Hash als Argument:

1
2
3
4
5
6
def bennant(opts = {:bennant1 = "Hallo", :benannt2 = "Welt!"})
  puts opts[:benannt1].to_s + " " + opts[:benannt2].to_s
end
#Ruby hat syntaktischen Zucker parat, der die geschweiften Klammern in Methodenaufrufen unn��tig macht
benannt(:benannt1 => "Wiedersehen", :benannt2 => "Welt!")
#=> Wiedersehen Welt!


Variable Argumentzahl (Methodenüberladung)

Es ist in Ruby nicht möglich, Methoden zu überladen. Stattdessen kann man eine variable Argumentanzahl benutzen, die der Methode dann als Array übergeben wird. Die Variable, welche die variablen Argumente aufnehmen soll, folgt, wenn vorhanden, nach den optionalen Argumenten und mit einem * davor:

1
2
3
4
5
6
7
8
def variable_args(pflicht1, opt1 = "T", *args)
  p args
end
variable_args("X", "U") #=> []
variable_args("X", "U", "TT", "Z") #=> ["TT", "Z"]
def nur_variable_args(*args)
#...
end


yield und Blockargument

yield

Natürlich gibt es auch Iteratoren, die man selbst definieren kann. Man kann einfach das Schlüsselwort yield benutzen, und schon wird der einer Methode mitgegebene Codeblock ausgeführt. Um zu überprüfen, ob überhaupt ein Block da ist, kann man Kernel#block_given? verwenden.

1
2
3
4
5
6
7
8
9
10
11
12
def mit_block
  if block_given?
    yield
  else
    puts "No block given!"
  end
end
mit_block #=> No block given!
mit_block do
  puts "Block!"
end
#=> Block!


Man kann yield Argumente übergeben, die dann vom Block »abgeholt« werden können:

1
2
3
4
5
6
7
8
def mit_block
  if block_given?
    yield("Block given!")
  else
    puts "No block given!"
  end
end
mit_block{|arg| puts arg} #=> Block given!


Blockargument

Wenn yield nicht genug ist, kann man auch ein Blockargument definieren, indem man einem Variablennamen ein & voranstellt. Das Blockargument muss immer das letzte Argument sein, nach verpflichtenden, optionalen und variablen Argumenten. Es enhält den mitgegebenen Codeblock als Proc-Objekt, dem in call wie bei yield auch Argumente mitgegeben werden können.

1
2
3
4
def mit_proc(&block)
  puts block.call
end
mit_proc{"Hello World"} #=> Hello World

Rückgabewerte

Eine Methode kann einen Wert zurückgeben, indem sie das Schlüsselwort return benutzt. Wenn eine Methode return erreicht, stoppt sie und gibt den angegebenen Wert zurück. Wenn man keinen Wert übergibt, wird das Ergebnis des letzten Ausdrucks verwendet.

1
2
3
4
5
def plus_eins(zahl)
  return zahl + 1
  puts "Das hier wird nie ausgef��hrt."
end
puts plus_eins(2) #=> 3


Optionales return

return ist optional, wie man ja auch an den oberen Beispielen gesehen hat. Wenn man return weglässt heißt das aber nicht, dass eine Methode keinen Wert bzw. nil zurückgibt, stattdessen wird einfach der letzte ausgewertete Ausdruck zurückgegeben:

1
2
3
4
def no_return
  1 + 1
end
puts no_return #=> 2

Methodenarten

Instanzmethoden

Eine Instanzmethode ist eine Methode, die von Instanzen von Klassen aufgerufen werden kann:

1
2
3
4
5
6
7
class Klasse
  def instanzmethode
    puts "Hello world!"
  end
end
x = Klasse.new
x.instanzmethode #=> Hello world!


Klassenmethoden

Eine Klassenmethode wird von einer Klasse oder einem Modul ausgeführt.

1
2
3
4
5
6
7
8
9
10
11
12
  module A
    class B
      def self.klassenmethode
        puts "Klasse B"
      end
    end
  def self.modulmethode
    puts "Modul A"
  end
end
A::B.klassenmethode #=> Klasse B
A.modulmethode #=> Modul A


Singletonmethoden

Singletonmethoden sind Methoden, die nur ein spezielles Objekt beherrscht; Klassenmethoden zum Beispiel sind Singletonmethoden auf dem Objekt einer Klasse.

1
2
3
4
5
6
7
8
9
class A
end
x = A.new
y = A.new
def x.singletonmethode
  puts "hello"
end
x.singletonmethode #=> hello
y.singletonmethode #=> NoMethodError


Zusammenfassung der Syntax

Die Syntax einer Methode lautet also:

def [[objekt.]][methodenname]([verpflichtende_argumente][[, optionale_argumente]][[, *variable_argumente]][[, &blockargument]])
  [Code]
  [[yield]]
  [[return [[rückgabewert]]]]
end

Aliasing

Methoden zusätzlich zu ihrem Namen einen weiteren Namen zu geben, kann man über Aliasing erreichen. Dadurch wird eine Kopie der Methode angefertigt, die exakt dasselbe macht wie ihr Original, nur eben unter anderem Namen. Man kann das auch als "BackUp-Technik" benutzen, da man auf diese Art und Weise die Originalmethode einfach überschreiben kann, die Kopie aber weiterhin das gleiche wie vorher macht. Die Syntax für das alias-Schlüsselwort ist wie folgt:

alias neuer_methodenname alter_methodenname

Zwischen beiden Namen ist kein Komma!

Instanzalias

Aliasing von Instanzmethoden ist einfach machbar:

1
2
3
4
5
def a
  puts "a"
end
alias b a
b #=> a

Klassenalias

Bei Klassenmethoden ist es schon ein wenig kniffliger.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A
  def self.a
    puts "a"
  end
  alias b a
end
#=> NoMethodError
#Einfach den syntaktischen Zucker herausnehmen: Klassenmethoden sind Instanzmethoden der Singletonklasse einer Klasse, also: 
class A
  class << self
    def a #Die Methode k��nnte auch als self.a in der Klasse A definiert werden, aber das hier dient der ��bersichtlichkeit
      puts "a"
    end
    alias b a
  end
end
A.b #=> a

Modulalias

Ein Alias einer Modulmethode kann genauso erstellt werden wie der einer Klassenmethode.

1
2
3
4
5
6
7
8
9
module A
  def A.a
    puts "a"
  end
  class << self
    alias b a
  end
end
A.b #=> a

Änderungen an Methoden und der Klasse Method zu Ruby 1.9

Hier werden Änderungen an Methoden zu Ruby 1.9.1 gelistet, sobald ein FeatureFreeze stattgefunden hat.

Siehe auch