Zum besseren Verständnis zuerst Programme als Kochbücher lesen...
In der Mathematik ist eine Funktion ein Platzhalter (Variable) für eine Berechnungsvorschrift,
Beispiel für die Definition einer Funktion mit dem Namen f1:
f1: IR->IR+ mit f1(x) = 2x2+5
Die Funktion f1 hat als Eingabe die Reellen Zahlen und berechnet gemäß ihrer Vorschrift ein Ergebnis, das ist ihre Ausgabe,
Beispiel für die Eingabe 3:
f1(3) = 2*3*3+5 = 23 sprich: eff eins von drei hat den Wert dreiundzwanzig
Es gibt auch Funktionen mit zwei und mehr Eingaben:
f2: IR X IR->IR mit f2(x,y) = x2+3y
Die Funktion f2 berechnet aus zwei Eingaben x,y eine Ausgabe. Die Liste der Eingabevariablen nennt man auch Parameter der Funktion.
Der Zahlenbereich für die Eingabe wird Definitionsbereich, der für die Ergebnisse Wertebereich der Funktion genannt.
Im Zusammenhang mit Programmen versteht man unter einer Funktion eine gekapselte Menge von Programmzeilen (Anweisungen).
Weitere Bezeichnungen für Funktionen: Unterprogramme, Prozeduren, Module, Methoden.
Wie werden die Bezeichnungen richtig verwendet?
Unterprogramm | Überbegriff, eine Folge von Anweisungen aufrufbar zusammenfassen |
---|---|
Modul | Begriff aus der Systemgestaltung meint Unterprogramm, Ein- und Ausgabe sollen hervorgehoben werden |
Prozedur | Unterprogramm ohne Rückgabe, kann eine Eingabe haben, gibt's in Pascal aber nicht in Java und C |
Funktion | Unterprogramm mit Ein- und Ausgabe, da es in Java und C keine Prozeduren gibt, wird der Begriff dort auch für Prozeduren verwendet |
Methode | nennt man eine Funktion in Zusammenhang mit einem Objekt |
Ein Programm besteht aus einer Folge von Anweisungen (Befehlen), will man einzelne Anweisungsfolgen bündeln, verpackt man sie in eine Funktion.
Damit sind diese Anweisungsfolgen unter dem Namen der Funktion aufrufbar.
Beispiel: Kochstudio: Statt jeden einzelnen Schritt beim "Nudeln kochen" immer wieder in den Rezepten anzugeben, wird dafür die Nudeln_kochen(Nudeln) Funktion verwendet.
Der ganze Zugriff auf die Programm-Oberfläche geschieht über vordefinierte Methoden.
Vorteile:
Nachteile:
Anweisungen beziehen sich auf die Umgebung in denen sie stehen:
Auflaufform = Nudeltopf + Gemüsetopf; // Der Inhalt (Wert) von den Töpfen wird in die Form gegeben
kann nur ausgeführt werden, wenn es erreichbare Gefäße (Variablen) "Auflaufform", "Nudeltopf" und "Gemüsetopf" gibt.
Diese Gefäße (Variablen) sind nur erreichbar, wenn sie bereits in der Arbeitsfläche eingebaut sind oder wir uns die Gefäße bereitstellen (deklarieren). Dabei sollte Nudeltopf und Gemüsetopf einen bestimmten Inhalt (Wert) haben... ;-)
Durch Anweisungen kann die Programmumgebung verändert werden, wie beim Kochen werden Gefäße, Arbeitsgeräte und Material dazu benötigt. Wenn ich einen Kochtopf brauche muß er sich in Reichweite auf der Arbeitsfläche befinden, im Salzstreuer sollte sich eine Menge Salz befinden... D.h. bevor ich eine Variable verwende muß sie deklariert und gegebenenfalls auch initialisiert sein:
Kochtopf Nudeltopf; // Einen Kochtopf für Nudeln bereitstellen Streuer Salzstreuer = 10g; // Einen Streuer mit 10g Salz bereitstellen Nudeltopf = 500ml; // Einen halben Liter Wasser in den Topf Nudeltopf= Nudeltopf + Salzstreuer.Priese(); // Nimm den Nudelkochtopf und gebe eine Prise Salz dazu
Hinweis. Leider kann man mit Java und C++ noch nicht so einfach kochen, denn was ein Kochtopf oder ein Streuer ist, kennt die Programmierumgebung noch nicht ;-)
Ein modernes Programm besteht aus einer Menge von Funktionen, Kochbuch von Rezepten. Wenn Du mit der Maus auf einen Button klickst, rufst Du ein Rezept auf. Dem Button ist ein Rezept zugeordnet, es wird eine Rezeptfunktion "ButtonClick" aufgerufen. Die Anweisungen die in dieser Funktion stehen werden dann ausgeführt.
Bei den folgenden Beispielen gilt die Vereinbarung das gerade "ButtonClick()" aufgerufen wurde und das Ergebnis mit "Ausgabe(Ergebnis)" sichtbar gemacht wird.
void ButtonClick(){ // dieses Rezept wird ausgeführt Ausgabe(4); }
Dieses Rezept gibt einfach die Zahl 4 aus. Nun ein Beispiel mit Variablen
int a=10,b=5,c; // Variablen vereinbaren void ButtonClick(){ // dieses Rezept wird ausgeführt c=a+b; // Wert von a und b addieren und in c abspeichern (merken) Ausgabe(c); // Wert von c ausgeben }
Drei Variablen a,b,c werden deklariert (bereitgestellt) in a und b soll schon ein Wert (Inhalt) sein, sie werden zusätzlich initialisiert. Beim Aufruf von ButtonClick passiert folgendes:
Aus den Variablen a und b werden die Werte geholt und addiert, das Ergebnis landet in c, es wird c zugewiesen. Die Ausgabe ist 15.
Wichtig: a und b wurden nicht verändert, c hat nun den Wert 15.
Wir brauchen die Variable c nicht unbedingt:
int a=10,b=5; // Variablen vereinbaren void ButtonClick(){ // dieses Rezept wird ausgeführt Ausgabe(a+b); }
Hat die gleiche Ausgabe 15, man kann das Ergebnis der Addition auch direkt ausgeben, allerdings ist das Beispiel mit dem c für Anfänger übersichtlicher.
Im nächsten Beispiel soll die Anweisung c=a+b in ein Unter-Rezept namens sum() verpackt werden:
int a=10,b=5,c; // Variablen vereinbaren void sum(){ // Unterprogramm namens sum() c= a+b; } void ButtonClick(){ // dieses Rezept wird ausgeführt sum(); // sum() aufrufen Ausgabe(c); }
Beim Aufruf von ButtonClick passiert folgendes:
Das Unter-Rezept (Unterprogramm, Funktion) sum() wird aufgerufen. c wird der berechnete Wert 15 zugewiesen, nach dem Ende des Unterprogramms geht die Verarbeitung bei der Ausgabe von c weiter. Die Ausgabe ist wieder 15.
Das Beispiel wurde so erweitert, daß ein sogenannter Seiteneffekt einer Funktion verdeutlicht werden kann:
int a=10,b=5,c; // Variablen vereinbaren void sum(){ // Unterprogramm namens sum() a= a-5; c= a+b; } void ButtonClick(){ // dieses Rezept wird ausgeführt sum(); // sum() aufrufen sum(); // sum() aufrufen Ausgabe(c); }
Welcher Wert wird ausgegeben? Welchen Wert hat a nach dem zweiten Aufruf von sum()?
Beim Aufruf von Summe wird die Variable a verändert, eine Auswirkung außerhalb einer Funktion nennt man einen Seiteneffekt der Funktion.
Wie kann bei dem Beispiel mit sum() die Variable c eingespart werden?
Du hast Dich sicher schon über das "void" gewundert. In Java und C++ gibt es nur Funktionen (in Pascal gibt es eine eigene Bezeichnung für Unterprogramme ohne Rückgabe: "procedure"). Bei Funktionen ist es üblich etwas zurück zu geben, die Funktion hat einen Wert. Wenn man nichts bestimmtes zurückgeben will, wird das "void" genannt.
Im folgenden Beispiel gibt sum() den Wert der Addition zurück, die Funktion hat den Typ int, d.h. ihr Ergebnis ist vom typ int:
int a=10,b=5; // Variablen vereinbaren int sum(){ // Unterprogramm namens sum(), Rückgabe vom Typ int return a+b; } void ButtonClick(){ // dieses Rezept wird ausgeführt Ausgabe(sum()); // sum() aufrufen und den Wert von sum() ausgeben }
Mit der Anweisung "return" wird der Wert der Funktion bestimmt, die Funktion wird mit diesem Wert sofort verlassen.
Beispiel aus Java: Methode getText() eines Textfeldes, Rückgabewert ist vom Typ "String".
Dieses Beispiel zeigt eine Funktion mit Eingabe und Ausgabe:
int a=10; // Variablen vereinbaren int plusfive(int b){ // Unterprogramm namens plusfive(int b), Rückgabe vom Typ int b= b+5; // zu b 5 addieren; return b; // b zurückgeben } void ButtonClick(){ // dieses Rezept wird ausgeführt Ausgabe(plusfive(a)); // plusfive(a) aufrufen und den Wert von plusfive(a) ausgeben }
Beim Aufruf von ButtonClick passiert folgendes:
plusfive(int b) wird mit dem Wert von a also 10 aufgerufen. (int b) nennt man den Parameter oder die Schnittstelle der Funktion. Der Wert 5 wird der Parametervariablen b der Funktion übergeben, nennt man "call by value", weil er in b kopiert wird. Innerhalb der Funktion steht nun die Variable b zur Verfügung. Auf den Wert von b wird nun 5 addiert und das Ergebnis zurückgegeben. Das ist dann der Wert von plusfive(10). Die Ausgabe 15.
Der Platz für die Variable int b wird erst beim Aufruf der Funktion reserviert und nach Ende der Funktion wieder freigegeben. Das ist wie mit dem Kochtopf zum Nudeln kochen, der nach dem Umfüllen der Nudeln in die Auflaufform wieder frei ist. Zum Umrühren bedarf es eines Kochlöffels, einer Lokalen Variablen:
int a=10; // Variablen vereinbaren int plusfive(int b){ // Unterprogramm namens plusfive(int b), Rückgabe vom Typ int int c; // lokale Variable c c= b+5; // zu b 5 addieren und in c speichern; return c; // c zurückgeben } void ButtonClick(){ // dieses Rezept wird ausgeführt Ausgabe(plusfive(a)); // plusfive(a) aufrufen und den Wert von plusfive(a) ausgeben }
Die Variablen b und c sind nur innerhalb der Funktion vorhanden (sichtbar), sie werden beim Aufruf der Funktion reserviert. Außerhalb der Funktion existieren sie nicht!
Wichtig: Lokale Variablen verdecken globale Variablen mit dem selben Namen:
int a=10; // Variablen vereinbaren int plusfive(int b){ // Unterprogramm namens plusfive(int b), Rückgabe vom Typ int int a; // lokale Variable a, verdeckt globales a a= b+5; // zu b 5 addieren und in a speichern; return a; // a zurückgeben } void ButtonClick(){ // dieses Rezept wird ausgeführt Ausgabe(plusfive(a)); // plusfive(a) aufrufen und den Wert von plusfive(a) ausgeben }
Die lokale Variable a in der plusfive-Funktion verdeckt das globale a, d.h. was innerhalb von plusfive mit a gemacht wird hat keine Auswirkung auf das globale a, der Wert bleibt unverändert! Gilt auch für die Parametervariable b, sie würde auch eine globales b entsprechend verdecken.
Beispiel aus Java: Die Methode setText("Hallo") des Textfeldes oder des Labels. Wirkung durch Seiteneffekt:
int a=10,c; // Variablen vereinbaren int plusfive(int b){ // Unterprogramm namens plusfive(int b), Rückgabe vom Typ int c= b+5; // zu b 5 addieren und in c speichern; } void ButtonClick(){ // dieses Rezept wird ausgeführt plusfive(a) Ausgabe(c); // plusfive(a) aufrufen, Seiteneffekt auf c und den Wert von c ausgeben }
Hier besteht die Wirkung durch den Seiteneffekt auf die globale Variable c, in der das Ergebnis gespeichert wird.
Funktionen sind Unterprogramme. Durch Verwenden von Parametern und lokalen Variablen können globale Variablen eingespart und die Auswirkungen durch die Funktionen (Seiteneffekte) überschaubarer gehalten werden. Funktionen können einen Wert zurückgeben, dadurch kann eine globale Variable zur Werteübergabe eingespart werden. Die Umgebung moderner Programmiersprachen besteht aus Objekten, deren Eigenschaften werden durch den Aufruf der vorgesehenen Methoden verändert. Durch das Kapseln von Eigenschaften in Objekten macht die Umgebung beherrschbarer, unerwünschte Seiteneffekte werden vermieden.
Zu den Aufgaben...