Hinein und wieder heraus - Theorie Lektion 4

Erstellt von Frithjof Sun, 22 Jul 2007 04:44:00 GMT

Die letzte Lektion lehrte dich, was in Ruby eine Methode ist—eine Menge von Codezeilen, denen du einen Namen verpasst. Du rufst die Methode auf, indem du den Namen der Methode verwendest.

Eine Methode ist aber eigentlich noch mehr. Sie ist wie eine Maschine. Das Aufrufen der Methode bei ihrem Namen ist, als wenn du eine Maschine einschaltest. Wenn die Maschine fertig ist, hört sie auf zu arbeiten—die Methode hat alle Codezeilen ausgeführt.

Und wo ist das mehr? Bevor du eine Maschine arbeiten lässt, kannst du normalerweise etwas in die Maschine hineingeben. Ist sie fertig mit ihrer Arbeit, dann liefert sie ein fertiges Produkt. Schau dir die Goldmaschine in der Abbildung an. Sie erhält als Eingabe Goldsteine (Felsbrocken, in denen Gold eingeschlossen ist) und liefert als Ausgabe Goldbarren. Wie sie das genau macht, wissen wir nicht. Irgendwie wird sie die Steine erhitzen, das Gold schmilzt und läuft heraus, wird aufgefangen in Formen gegossen… Egal, Hauptsache sie macht, wozu sie konstruiert wurde.

Oder stell dir eine Kaffeemaschine vor! Es ist Sonntagmorgen und du möchtest Mama, die noch friedlich schläft, mit einem Tässchen Kaffee überraschen. Du gibst folgendes in die Kaffeemaschine hinein:
  1. Ein wenig Wasser
  2. Einen Kaffeefilter
  3. Etwas Kaffeepulver

Du schaltest die Maschine ein. Sofern sie korrekt funktioniert, wird sie dir Kaffee zubereiten, der in eine Glaskanne herausläuft. Nun nur noch in eine schöne Sonntagstasse füllen, etwas Sahne dazu, vielleicht Zucker, Untertasse nicht vergessen (Mamas mögen sowas!), auf das Tablett neben das leckere Marmeladebrötchen und das frisch gekochte Ei (das hast du mit einer anderen Maschine erledigt) und ab zu Mama! So kriegst du sie immmer wach, egal wie früh es ist…

Eine Methode ist wie eine Maschine, hatte ich gesagt. Wie gibst du nun etwas in die Methode hinein? Und wie bekommst du etwas aus der Methode heraus? Schauen wir uns an, wie das mit einer Rubymethode aussieht:


# theorie_04.rb

def kaffee_maschine(wasser, filter, pulver)
  # Die Maschine beginnt mit dem Heizen des Wassers
  puts "=> #{wasser} Wasser werden heisser und heisser..." 
  puts "=> Pumpe das Wasser durch ein Roehrensystem..." 
  puts "=> Und lasse es auf #{pulver} Pulver in den #{filter} fallen.\n" 
  # Das heisse Wasser laeuft durch das Pulver im Filter in die Glaskanne
  # darunter, das geht von alleine, da braucht die Maschine nichts 
  # weiter zu machen 
  # ...
  # Maschine ist fertig:
  puts "=> Fauchen und Dampf ablassen als Zeichen, dass ich fertig bin..." 

  # Fertigen Kaffee zurueckliefern
  return "Bitte schön: Glaskanne mit #{wasser} leckerem Kaffee" 
end

wasser = "2 Tassen (okay Papa kriegt auch eine)" 
filter = "Kaffeefilter Groesse 4 (der aus dem Aldi)" 
pulver = "Mhhmm, riecht das lecker. 2 Löffel!" 

kaffee_fuer_mama = kaffee_maschine(wasser, filter, pulver)

puts "Kaffee ist fertig!" 
puts kaffee_fuer_mama

Schauen wir uns den Code genauer an!

Zunächst definierst du eine Methode mit dem Namen kaffee_maschine. Die Methode umfasst alle Codezeilen bis zum zugehörigen end. Die Methode selbst kocht uns natürlich keinen echten Kaffee, es ist ja nur ein Rubyprogramm. Daher gibt es nur aus, was es tun würde, wenn es eine echte Kaffeemaschine wäre.

Hier ist aber etwas neu. Hinter dem Namen der Methode steht ein Paar runde Klammern, und innerhalb der Klammern stehen drei Variablennamen wasser, filter und pulver. Merke also, wenn du möchtest, dass jemand etwas in deine Methode (Maschine) hineintun können soll, dann schreibst du hinter den Methodennamen in runde Klammern für jedes Ding einen Variablennamen.

Innerhalb der Methode kannst du dann die Variablen wie ganz gewöhnliche Variablen verwenden und irgendetwas damit machen.

Ist die Methode (Maschine) fertig, kann sie das Ergebnis (das fertige Produkt) zurückgeben. Das passiert in der letzten Zeile vor dem Ende der Methode mit dem return Befehlt. Nach dem return steht das, was du deine Methode zurückgeben lassen möchtest. Im Beispiel oben ist es einfach die Mitteilung, dass in der Glaskanne 2 Tassen Kaffee sind.

Noch einige Besonderheiten

Die Variablen, die du hinter dem Methodennamen aufzählst, sind wirklich nur innerhalb der Methode verwendbar. Außerhalb der Methode sind die Variablen nicht bekannt. Wir haben zwar unterhalb der Methode diese 3 Variablen noch einmal stehen, das sind aber komplett andere Variablen, die heißen bloß genauso! Wir könnten sie oder die Variablen hinter dem Methodennamen ganz anders nennen, und das Programm funktionierte noch immer. Bedenke nur, dass du die Variablen dann auch dort ändern musst, wo du sie verwendest.



def kaffee_maschine(wasser, filter, pulver)
  # Die Maschine beginnt mit dem Heizen des Wassers
  ...
  return "Bitte schön: Glaskanne mit #{wasser} leckerem Kaffee" 
end

wieviel_wasser = "2 Tassen (okay Papa kriegt auch eine)" 
welcher_filter = "Kaffeefilter Groesse 4 (der aus dem Aldi)" 
wieviel_pulver = "Mhhmm, riecht das lecker. 2 Löffel!" 

kaffee_fuer_mama = kaffee_maschine(wieviel_wasser, welcher_filter, wieviel_pulver)

puts "Kaffee ist fertig!" 
puts kaffee_fuer_mama

Bei der Rückgabe des Ergebnisses kannst du das Wörtchen return auch weglassen, wenn die Rückgabe in der letzten Zeile der Methode erfolgt. Das muss nicht zwingend immer die letzte Zeile vor dem end sein. Sondern es muss die letzte Zeile sein, die Ruby während der Abarbeitung deiner Methode ausführt, bevor Ruby die Methode verlässt. Hast du beispielsweise eine IF-Abfrage in der Methode, könnte es mit und ohne return so aussehen.


# Methode mit return

def mehr_kaffee(soviel_hatte_sie_schon)
  if soviel_hatte_sie_schon > 2
    return "gibt nix mehr!" 
  else
    return "Okay, noch eine Tasse!" 
  end
end


# Methode ohne return

def mehr_kaffee(soviel_hatte_sie_schon)
  if soviel_hatte_sie_schon > 2
    "gibt nix mehr!" 
  else
    "Okay, noch eine Tasse!" 
  end
end

Die Zeile, die im letzten Codebeispiel als letztes ausgeführt wird, hängt ab vom Wert, der in der Variablen soviel_hatte_sie_schon übergeben wurde. Ist der Wert größer 2, gibt die Methode “gibt nix mehr!” zurück, auch wenn diese Codezeile nicht die letzte in der Methode ist. Sie ist aber die letzte, die unter diesen Bedingungen von Ruby ausgeführt wird. Denn in den else-Zweig gelangt Ruby nur, wenn der Wert der übergebenen Variablen kleiner oder gleich 2 ist.

Üben mit Peter und Livia

Livia: Schreibe eine Methode mit dem Namen maximum, die zwei Zahlen entgegen nimmt, dann entscheidet, welche Zahl die größere ist und diese dann als Ergebnis zurückliefert.

Peter: Schreibe eine Methode mit dem Namen verketten, die zwei Zeichenketten entgegen nimmt, sie beide aneinander hängt und die so neu entstandene Zeichenkette zurück gibt.

Programme aufteilen - Theorie Lektion 3

Erstellt von Frithjof Sat, 14 Jul 2007 21:28:00 GMT

Du bist noch immer unterwegs zu Lektion 11, wo du dann beginnen wirst, ein Spiel zu programmieren.

Aus Lektion 7 weißt du bereits, dass lange Programme zunehmend schwieriger zu lesen sind. Du reihst eine Zeile an die nächste. Was machst du, wenn du im Verlauf des Programms an eine Stelle kommst, wo du genau denselben Code brauchen würdest, den du weiter oben schon einmal verwendet hast? Nochmal hinschreiben? Naja, das stinkt ja bereits schon beim nur dran denken. Du erinnerst dich, was stinkender Code ist?

Du lernst in dieser Theorielektion eine Möglichkeit kennen, die du sehr häufig brauchen wirst wenn es darum geht, gleichen Code wiederzuverwenden, ohne ihn erneut hinschreiben zu müssen.

Die Idee ist ganz einfach. Du schreibst deine Zeilen Code, die du häufiger verwenden möchtest, in eine Datei und gibst ihnen dabei einen Namen. Ja richtig gehört, du denkst dir einen Namen für die Programmzeilen aus. Immer dann wenn du anschließend die Zeilen Code verwenden möchtest, verwendest du stattdessen nur den Namen. Du rufst den Code bei seinem Namen!

Sagen wir, du willst in deinem Programm an verschiedenen Stellen die Aufforderung zur Eingabe einer Zahl verwenden


puts "Bitte gib eine Zahl größer 0 ein:" 

Du denkst dir als Namen frag_sie aus. Das Benennen des Codes sieht dann so aus:


def frag_sie
  puts "Bitte gib eine Zahl größer 0 ein:" 
end

Das Schlüsselwort def leitet die Benennung des Codes ein, gefolgt von dem Namen den du dir überlegt hast. Am Ende der Codezeilen wird die Benennung mit end abgeschlossen.

Nun kannst du den benannten Codeabschnitt verwenden, indem du ihn bei seinem Namen aufrufst. Dabei musst du nur darauf achten, dass der Aufruf natürlich nach der Benennung steht.


# theorie_03.rb

# Zuerst den Code mit einem Namen versehen
def frag_sie
  puts "Bitte gib eine Zahl größer 0 ein:" 
end

# Dann den benannten Code verwenden
frag_sie
a = gets

# Noch eine Zahl verlangen
frag_sie
b = gets

# und noch eine, weils so einfach ist
frag_sie
c = gets

Das Schlüsselwort def leitet sich von Definieren ab. Das Gebilde vom def über den Namen, den Code bis zum end hin nennt man auch ein Unterprogramm, weil es innerhalb eines anderen Programmes existiert. Andere Bezeichnungen dafür sind noch Subroutine, Funktion oder Methode.

Lass uns von nun an den Begriff Methode (d.h. eine Handlungsanweisung oder Art und Weise) dafür verwenden. Denn der benannte Code stellt eine Folge von Anweisungen dar, die bei Aufruf so ausgeführt werden.

Du hast also soeben deine erste Methode definiert, die Methode heißt frag_sie.

-
Update 15.07.2007

Üben mit Peter und Livia

Gestern Abend war es schon spät, Peter und Livia bereits in tiefen Schlaf gefallen. Heute morgen waren sie dann ganz enttäuscht, dass sie keine Übung zum Theorieartikel beisteuern konnten. Daher hier noch eine kleine Übung zu Methoden. Wie üblich erst selbst versuchen, wenn du nicht weiterkommst, Mama fragen, als letztes kannst du dann in der Lösung nachsehen.

Peter und Livia: Schreibe die Methode frag_sie so um, dass sie nach dem Namen der Anwenderin fragt. Schreibe zusätzlich noch eine Methode mit Namen sie_sagte, die ausgibt, was die Anwenderin eingegeben hatte. Verwende danach beide Methoden.

Lösungen

def frag_sie
  puts "Wie heisst du? " 
end

def sie_sagte
  a = gets
  puts "Aha, du heisst also #{a}" 
end

frag_sie
sie_sagte