Universität Paderborn Prof. Dr. Heike Wehrheim Kapitel 1: Grundlegende Programmierkonstrukte 1.5 Methoden: Funktionen und Prozeduren GPI, WS 07/08 249 Motivation Universität Paderborn Prof. Dr. Heike Wehrheim Bisher: Weiterbenutzung von einmal geschriebenen Programmteilen nur durch „copy-and-paste“ Aber: in größeren Programmen benötigt man dasselbe Teilprogramm unter Umständen öfters (z.B. Berechnung einer Wurzel, Sortieren eines Arrays, …) Funktionen und Prozeduren (auch: Methoden) erlauben es, dasselbe Teilprogramm mehrfach zu verwenden Funktionen und Prozeduren unterstützen einen strukturierten Entwurf: erst Algorithmus abstrakt beschreiben, dann schrittweise konkretisieren GPI, WS 07/08 250 Schrittweise Verfeinerung Universität Paderborn Prof. Dr. Heike Wehrheim Algorithmen zur Lösung komplexer Fragestellungen müssen schrittweise entworfen werden. Zuerst auf abstraktem Niveau festlegen, dann ins Detail gehen -> Prinzip der schrittweisen Verfeinerung Veranschaulichung am Kochrezept: Aufgabenstellung: Menü kochen Algorithmus abstrakt: koche Vorspeise koche Hauptgericht koche Dessert dann Teile konkretisieren: am Beispiel koche Dessert schneide Obst klein schlage Sahne mische Obst mit Sahne GPI, WS 07/08 251 Vorteile Universität Paderborn Prof. Dr. Heike Wehrheim erreicht wird ein hohes Maß an Strukturierung und Modularisierung der Programme das erhöht die Lesbarkeit, Wiederverwendbarkeit, Änderbarkeit, Wartbarkeit, … Vorlesung „Softwareentwurf“ (dazu trägt übrigens auch die Benutzung von „sprechenden“ Variablennamen und das Schreiben von Kommentaren bei!) … und reduziert meist auch die Anzahl der Fehler! Java bietet dafür eine Reihe von Konzepten an, erste nun im folgenden, weitere später. GPI, WS 07/08 252 Funktionen Universität Paderborn Prof. Dr. Heike Wehrheim Funktionen dienen zur Gliederung von Programmen. Eine Funktion soll eine übersichtliche Teilaufgabe erledigen. Eine Funktion kann Parameter verwenden, deren Werte erst im Aufruf angegeben werden. Eine Funktion berechnet ein Ergebnis und/oder verändert den Zustand in ihrer Umgebung. Es können nicht nur vordefinierte Funktionen verwendet, sondern auch eigene Funktionen geschrieben werden. Funktion auch oft: Methode mit Ergebnis Prozedur: Methode ohne Ergebnis GPI, WS 07/08 253 Anschauliches Beispiel Universität Paderborn Prof. Dr. Heike Wehrheim Name der Funktion Ergebnis Funktionsdefinition: kocheWasser (x : Liter) -> kochendes Wasser messe x Liter Wasser ab; fülle in Wasserkocher; Parameter warte bis kocht; liefere kochendes Wasser ab; Benutzung (Aufruf): z.B. kocheWasser(20) GPI, WS 07/08 254 Funktionsdefinition Universität Paderborn Prof. Dr. Heike Wehrheim Syntax: Modifizierer Ergebnistyp Funktionsname (formale Parameter) Block Beispiel: public static double toFahrenheit (double celsius) { return celsius * 9 / 5 + 32; } public und static sind hier Modifizierer, andere werden noch später kommen GPI, WS 07/08 255 Funktionsdefinition II Ergebnistyp Name der Funktion Universität Paderborn Prof. Dr. Heike Wehrheim Parameterliste: Typ und Name public static int fak (int n) { Lokale Variable int ergebnis = 1; for (int i = 1; i <= n; i++) { ergebnis = ergebnis * i; }; return ergebnis; Bezugnahme auf } GPI, WS 07/08 Beenden der Berechnung und Rückgabe des Ergebnisses den Wert des Parameters 256 Funktionskopf Universität Paderborn Prof. Dr. Heike Wehrheim public static int fak (int n) Definiert die Signatur (Typen der formalen Parameter und des Ergebnisses der Funktion). Hier fak: int -> int Der Ergebnistyp und die Parametertypen können beliebige Typen sein (auch Arrays). Eine Funktion kann beliebig viele Parameter besitzen, insbesondere auch gar keine. GPI, WS 07/08 257 Funktionsrumpf Universität Paderborn Prof. Dr. Heike Wehrheim Der Funktionsrumpf legt die Berechnungsvorschrift fest (ein Anweisungsblock). Im Funktionsrumpf kann man sich auf die (beim Aufruf übergebenen) Parameter beziehen. Dazu benutzt man deren Namen wie Variablen. Durch die return-Anweisung wird die Berechnung der Funktion beendet, und der Wert des Ausdrucks hinter return wird als Ergebnis zurückgegeben. Zur Berechnung kann man lokale Variablen definieren, die beim Beenden der Funktion wieder „vergessen“ werden. GPI, WS 07/08 258 Funktionsaufrufe Universität Paderborn Prof. Dr. Heike Wehrheim Funktionsname (aktuelle Parameter); Die aktuellen Parameter werden ausgewertet und die Funktion mit den Parameterwerten aufgerufen. z.B. toFahrenheit(21) , toFahrenheit(temp+10), fak(3*7-4) Der von der Funktion zurückgegebene Wert kann normal benutzt werden, also z.B. in Ausdrücken verwendet werden. z.B. fahr = toFahrenheit(14); wert = fak(20 – zahl) + 1; GPI, WS 07/08 259 Beispiel 1 Universität Paderborn Prof. Dr. Heike Wehrheim double a, wurzel; ... // Definition von a wurzel = Math.sqrt(a + 5.8)*6.7; // Vordefinierte Wurzelfunktion GPI, WS 07/08 260 Beispiel 2 Universität Paderborn Prof. Dr. Heike Wehrheim double cDegree = 10; double fDegree; fDegree = toFahrenheit(cDegree); System.out.println (toFahrenheit(cDegree+10)); GPI, WS 07/08 261 Beispiel 3 Universität Paderborn Prof. Dr. Heike Wehrheim int zahl = 5; int ergebnis; ergebnis = fak(fak(zahl)); oder Funktionsaufrufe geschachtelt ergebnis = fak(5) * fak(zahl); GPI, WS 07/08 262 Reihenfolge von Parametern Universität Paderborn Prof. Dr. Heike Wehrheim static boolean eineFunktion (int zahl1,boolean wert,int zahl2) … boolean b; int eineZahl, nochEineZahl; eineFunktion(eineZahl,b,nochEineZahl); // ok eineFunktion(eineZahl,nochEineZahl,b); // nicht ok eineFunktion(eineZahl,b); // nicht ok GPI, WS 07/08 263 Wo hinschreiben? Universität Paderborn Prof. Dr. Heike Wehrheim Beispiel: public class Fakultaet { static int fak (int n) { int ergebnis = 1; for (int i = 1; i <= n; i++) { ergebnis = ergebnis * i; }; return ergebnis; } Hier Funktionsdefinition public static void main (String [] args) { int zahl = 5; int ergebnis = fak(5); } Hier Funktionsaufruf } GPI, WS 07/08 264 Weiteres Beispiel – Ausgabe? Universität Paderborn Prof. Dr. Heike Wehrheim class MathFunktion { static int max (int zahl1, int zahl2) { if (zahl1 > zahl2) return zahl1; else return zahl2; } public static void main (String [] args) { int maximum, ergebnis; int ersteZahl = 15; int zweiteZahl = 42; }} maximum = max(ersteZahl, zweiteZahl); System.out.println("Das Maximum ist " + maximum); ergebnis = max((ersteZahl * 10) + 3, zweiteZahl - 4); System.out.println("Das Ergebnis ist " + ergebnis); MathFunktion.java GPI, WS 07/08 265 Eigene Aufgabe Universität Paderborn Prof. Dr. Heike Wehrheim a) Schreiben Sie eine Funktion, die die Differenz von zwei (int-)Zahlen berechnet. b) Schreiben Sie eine Funktion, die berechnet, ob eine Zahl größer 100 ist. Welche und wieviele Parameter brauchen die Funktionen? Was ist jeweils der Ergebnistyp? GPI, WS 07/08 266 Lösung Universität Paderborn Prof. Dr. Heike Wehrheim static int differenz(int zahl1, int zahl2) { return zahl1 – zahl2; } static boolean groesserHundert(int zahl) { return zahl > 100; } GPI, WS 07/08 267 Ausführung von Funktionen Universität Paderborn Prof. Dr. Heike Wehrheim Deklaration: Modifizierer Ergebnistyp Funktionsname (formale Parameter) Block Aufruf: Funktionsname(aktuelle Parameter) Zur Ausführung eines Aufrufes wird Speicher angelegt für die formalen Parameter, das Ergebnis und die lokalen Variablen der Funktion. Parameterübergabe „call-by-value“: Die formalen Parametervariablen werden mit den Werten der entsprechenden aktuellen Parameter initialisiert. Eine Anweisung return Ausdruck; beendet den Aufruf und bestimmt sein Ergebnis. Es können mehrere Return Anweisungen im Funktionsrumpf stehen. Der Typ des Ausdrucks hinter return muss dem Ergebnistyp der Funktion entsprechen. GPI, WS 07/08 268 Universität Paderborn Prof. Dr. Heike Wehrheim Illustration Call-by-value : fak 4 n 24 ergebnis Rückgabewert Bei Aufruf: 4 zahl • Wert von aktuellem Parameter zahl bestimmen • formalen Parameter n mit Wert belegen static int fak (int n) {int ergebnis = 1; … } … zahl = 4; … fak(zahl); GPI, WS 07/08 269 Universität Paderborn Prof. Dr. Heike Wehrheim Illustration II fak(fak(3)) (jeder Funktionsaufruf hat eigene Kopie der Variablen) 3 n fak(3) 6 ergebnis Rückgabewert 6 n fak(fak(3)) 720 ergebnis GPI, WS 07/08 Rückgabewert 270 Parameterübergabe Universität Paderborn Prof. Dr. Heike Wehrheim Es gibt noch andere Formen der Parameterübergabe: call by reference call by name Vorlesung GdP (Grundlagen der Programmiersprachen) Java benutzt call by value. GPI, WS 07/08 271 Call-By-Value I Universität Paderborn Prof. Dr. Heike Wehrheim class CallByValueIllustration { static int minusEins (int zahl) { zahl--; return zahl; } public static void main (String [] args) { int eineZahl = 20; int ergebnis; ergebnis = minusEins(eineZahl); System.out.println("Das Ergebnis ist " + ergebnis); System.out.println("Der Wert von eineZahl ist " + eineZahl); }} GPI, WS 07/08 CallByValueIllustration.java 272 Call-By-Value II Universität Paderborn Prof. Dr. Heike Wehrheim class CallByValueIllustration2 { static int minusEins (int zahl) { zahl--; return zahl; } public static void main (String [] args) { int zahl = 20; int ergebnis; ergebnis = minusEins(zahl); System.out.println("Das Ergebnis ist " + ergebnis); System.out.println("Der Wert von zahl ist " + zahl); }} GPI, WS 07/08 CallByValueIllustration2.java 273 Call-By-Value III Universität Paderborn Prof. Dr. Heike Wehrheim public class CallByValueIllustration4 { static boolean wertAendern (int [] einArray) { einArray[0] = 5; return true; } public static void main (String [] args) { int [] einIntArray = {1,1,1,1}; boolean b = wertAendern(einIntArray); System.out.println(einIntArray[0]); } } CallByValueIllustration4.java GPI, WS 07/08 274 Prozeduren Universität Paderborn Prof. Dr. Heike Wehrheim Prozeduren können eine Änderung ihrer Umgebung ((Objekt-)Zustand, Ein-, Ausgabe) bewirken, statt wie eine Funktion ein Ergebnis zu berechnen. Sie werden dann als Anweisungen aufgerufen; keine Benutzung in Ausdrücken. Statt Ergebnistyp hier void angeben. Beispiel: static void hello() { System.out.println(“Hello World“); } GPI, WS 07/08 275 Größeres Beispiel Universität Paderborn Prof. Dr. Heike Wehrheim Man möchte auf dem Zeilendrucker solche Muster ("Tickets") ausdrucken: ======= =55555= =55555= ======= Parameter: Breite in Zeichen (7), Höhe in Zeichen (4), Innen wiederholtes Zeichen ('5') Aufruf der Methode z.B. einTicket(7, 4, '5'); GPI, WS 07/08 276 Benutzung Universität Paderborn Prof. Dr. Heike Wehrheim Bei Aufruf von einTicket (10, 15, '?') entsteht ========== =????????= =????????= =????????= =????????= =????????= =????????= =????????= =????????= =????????= =????????= =????????= =????????= =????????= ========== GPI, WS 07/08 277 In Java Universität Paderborn Prof. Dr. Heike Wehrheim Zwei Prozeduren, eine für eine Zeile, eine für das ganze Ticket: static void eineZeile (int breite, char c) { System.out.print ('='); int i = 2; while (i < breite) { System.out.print (c); i = i+1; } System.out.println ('='); } static void einTicket (int breite, int höhe, char c) { eineZeile (breite, '='); int i = 2; while (i < höhe) { eineZeile (breite, c); i = i+1; } eineZeile (breite, '=');} TicketDrucker.java GPI, WS 07/08 278 Gültigkeitsbereiche Universität Paderborn Prof. Dr. Heike Wehrheim Variablendefinitionen gelten vom Ort der Definition bis zum Ende des Blocks, in dem sie stehen Block = Folge von Anweisungen in { } Gültigkeitsbereich, engl. scope GPI, WS 07/08 279 GPI, WS 07/08 280 args n loop square public static void main (String [] args) { int n = 10; int sum = 0; int loop = 0; while (loop < n) { loop++; int square = loop * loop; sum += square; } System.out.println(sum); } sum Beispiel Universität Paderborn Prof. Dr. Heike Wehrheim Weiteres Beispiel Universität Paderborn Prof. Dr. Heike Wehrheim } args ergebnis n zahl public static void main (String [] args) { int zahl = 5; int ergebnis = fak(5); } ergebnis public static int fak (int n) { int ergebnis = 1; for (int i = 1; i <= n; i++) { ergebnis = ergebnis * i; }; return ergebnis; } i public class Fakultaet { Zwei verschiedene Variablen ergebnis ! GPI, WS 07/08 281 Fragen I Universität Paderborn Prof. Dr. Heike Wehrheim Sei eine Funktion static int m(int x) { x = x + 1; return x * x; } deklariert. Welchen Wert hat i nach den folgenden Anweisungen? a) int i=2; i = m(i) + i; b) int i=2; i = m(m(i)) + m(i) + i; GPI, WS 07/08 282 Fragen II Universität Paderborn Prof. Dr. Heike Wehrheim Sei die Methode static void g (int x) { … } gegeben. Welche Verwendung von g ist zulässig? a) int i = g(3); b) int i = 3; g(i); c) for (int i = 0; i < 10; g(i) ) { … } GPI, WS 07/08 283