Funktionen Grundlagen
Schön das Sie es bis zu diesem Teil der Reihe „Swift lernen“ geschafft haben.
In dieser Lektion behandeln wir eines der schwierigsten Themen für Programmieranfänger. Wir lernen was Funktionen sind und wie wir diese verwenden und programmieren. Wer von euch Funktionen aus der Mathematik kennt, wird wohl recht schnell verstehen um was es sich in dieser Lektion drehen wird.
Solltet ihr dieses Thema meistern gibt es eigentlich kaum noch einen Grund warum man nicht weiter machen sollte. Es wird aber sicherlich einige Zeit dauern bis ihr ein solides Verständnis von diesem Thema habt. Gebt euch selbst die Zeit alles zu verstehen und wiederholt es ausreichend. Funktionen sind ein Schlüsselelement das permanent auf euch treffen wird.
Für diesen Teil gibt es auch ein Video Tutorial hier auf YouTube.
Inhalt
Begriffserklärung
Aufbau einer Funktion
Die erste eigene Funktion
Funktionen mit Parametern
Rückgabewerte
Begriffserklärung
Funktionen kann man auch als Unterprogramme oder Routinen bezeichnen. Sie haben die Möglichkeit wiederkehrenden Programmcode in eine Funktion zu schreiben, die Sie immer dann aufrufen wenn Sie es benötigen.
Eine Funktion hat einen immer einen eindeutigen Namen, man kann ihr Parameter übergeben und sie kann Werte zurück liefern.
Aufbau einer Funktion
Ein Funktion besteht aus einem Funktionskopf welcher den Namen der Funktion definiert. Ebenfalls kann man Parameter und einen oder mehrere Rückgabewerte in Swift definieren. Gefolgt vom Funktionskopf kommt der Funktionsrumpf in dem wir unsere eigentliche Funktion schreiben.
Schauen wir uns zuerst eine Funktion an die ohne Parameter oder Rückgabewert arbeitet.
1 2 3 |
func funktionsname() { } |
Mit dem Keyword func leiten wir die Funktion ein. Gefolgt wird das ganze von funktionsname was dem Namen unserer Funktion entspricht. Dieser muss einzigartig sein, da wir ansonsten Kollisionen bekommen.
In den leeren Klammern () können wir Parameter definieren. Vorerst verzichten wir aber der Einfachheit halber auf diese indem wir den Inhalt leer lassen.
Nach den Klammern folgen die geschweiften Klammern { } welche den Funktionsrumpf darstellen. In diesen schreiben wir später unseren Programmcode den die Funktion ausführen soll.
Die erste eigene Funktion
Unser Ziel ist es eine Funktion zu schreiben die einen String ausgeben soll den wir nach belieben definieren.
Wir schreiben hierfür folgende Funktion in unseren Playground.
1 2 3 |
func gibEtwasAus() { println("Meine erste Ausgabe mit einer Funktion") } |
Wir sehen wieder die Einleitung der Funktion mit dem Schlüsselwort func gefolgt vom Funktionsnamen. In unserem Funktionsrumpf rufen wir die Funktion println() auf der wir einen beliebigen String übergeben.
Zur Erinnerung: Damit wir die Ausgabe von println() sehen können, müssen wir den Assistant view von Xcode öffnen. Wer nicht mehr weiss wie das geht, kann das noch mal in dem Artikel über die Ausgabe von Strings und Zahlen nachlesen.
Damit die Funktion nun aufgerufen werden kann müssen wir nichts weiter tun als den Funktionsnamen zu schreiben und die leeren Klammern anzuhängen. Das mit den leeren Klammern trifft nur zu wenn wir keine Parameter haben, dazu gleich aber mehr.
Rufen wir Funktion auf und schauen uns die Ausgabe der Konsole an.
1 2 3 4 5 |
func gibEtwasAus() { println("Meine erste Ausgabe mit einer Funktion") } gibEtwasAus() |
Wir sehen das auf der Konsole unser definierter String ausgeben wird. Sie können den String nach belieben abändern. Probieren Sie doch einfach mal aus was passiert wenn Sie die Funktion mehrmals, indem Sie in den nächsten Zeilen noch ein paar mal den Aufruf gibEtwasAus() , schreiben.
Funktionen mit Parametern
An eine Funktion kann man Werte übergeben mit denen man arbeiten kann. In der Informatik nennen wir diese Werte bei Funktionen Parameter. Funktionen in Swift kann man mit unbegrenzt vielen Parametern nutzen, man sollte dies aber wenn möglich vermeiden, da zu viele Parameter auch unleserlich werden.
Ein Parameter muss immer mit einem Typ und einem Parameternamen definiert werden. Der Parametername ist dann später auch der Variablenname innerhalb der Funktion. Möchte man mehrere Parameter nutzen muss man diese mit Kommas voneinander trennen. Wichtig ist zu wissen das die Parameter die übergeben werden nicht verändert werden können. Man arbeitet immer auf einer Kopie des Originalwertes der übergeben wird. Wir lernen in einer späteren Lektion wie wir die übergebenen Parameter ändern können.
Schauen wir uns zuerst ein Beispiel an in dem wir eine Zahl vom Typ Int übergeben, welchen wir dann mit dem Wert „2“ multiplizieren und ausgeben.
1 2 3 4 5 6 |
func multipliziereMitZwei(wertA: Int) { var ergebnis = wertA * 2 println(ergebnis) } multipliziereMitZwei(2) |
In unserem Funktionskopf haben wir wieder unser Schlüsselwort func gefolgt von unserem Funktionsnamen multipliziereMitZwei. Diesmal sind die Klammern aber nicht leer. Wir sagen der Funktion das sie genau einen Parameter vom Namen wertA hat. Nach dem Parameternamen machen wir einen Doppelpunkt und definieren den Typ Int für unseren Parameter wertA. Danach schließen wir unsere Klammer und eröffnen den Funktionsrumpf mit den geschweiften Klammern.
Innerhalb der Funktion erstellen wir eine neue Variable var ergebnis der wir den Wert aus der Multiplikation wertA * 2 zuweisen. Wie man sehen kann nutzen wir in unserer Berechnung den im Funktionskopf definierten Parameter wertA.
Nach der Berechnung geben wir die Variable ergebnis mit der println() Funktion aus.
Damit unsere Funktion jetzt auch etwas tut müssen wir diese aufrufen. Das ganze machen wir ausserhalb der Funktion indem wir den Funktionsnamen schreiben und einen Wert übergeben. Das kann wie in unserem Beispiel einfach die Zahl „2“ sein oder auch der Wert aus einer Variable die irgendwo definiert ist. Später lernen wir wie man den Wert einer Funktion direkt an eine andere übergeben kann, ohne das wir diesen in einer Variable zwischenspeichern müssen. Dazu später mehr wenn wir mit Rückgabewerten arbeiten.
Mehrere Parameter
Um einen oder mehrere Parameter übergeben zu können müssen wir dieser im Funktionskopf mit einem Komma trennen. Bei dem Funktionsaufruf selbst müssen wir die zu übergebenden Werte ebenfalls mit einem Komma trennen.
1 2 3 4 5 6 |
func multipliziere(faktorA: Int, faktorB: Int) { var produkt = faktorA * faktorB println(produkt) } multipliziere(2,4) |
Der Funktionskopf und auch der Funktionsaufruf hat jetzt einen zweiten Parameter. Möchten Sie weitere Parameter haben müssen Sie wieder ein Komma schreiben und wie gelernt den nächsten Parameternamen mit Parametertyp schreiben.
In einer späteren Lektion lernen wir auch Variadic`s kennen mit denen wir unbegrenzt viele Parameter von einem Typ übergeben können.
Rückgabewerte
Eine Funktion hat die Möglichkeit ein Ergebnis zurückzuliefern. Dies kann von jedem beliebigen Typ sein. Ob Zahl, String oder Objekt. Das entscheiden nur Sie ganz alleine. In den meisten Programmiersprachen kann man nur einen Wert zurück geben. In Swift können wir mit Hilfe von Tuples auch mehrere zurückgeben. Dazu aber mehr in einer andere Lektion.
1 2 3 4 5 6 |
func multipliziere(faktorA: Int, faktorB: Int) -> Int { var produkt = faktorA * faktorB return produkt } println(multipliziere(2,4)) |
In unserem Funktionskopf haben wir jetzt nach den Parametern und vor dem Begin des Funktionsrumpfes einen Bindestrich mit dem größer Zeichen. Nachdem -> folgt der Datentyp den wir zurück geben möchten. In unserem Beispiel ist das Int.
Der Funktionsrumpf hat nun nicht mehr die Funktion println() mit dem wir den Wert vorher noch ausgeben haben. Stattdessen sehen wir return produkt. return weißt die Funktion an sich selbst zu beenden und falls wir in dem Wort return ein Wert haben wird dieser zurück gegeben.
Wenn Sie kein return definieren obwohl Ihre Funktion einen Rückgabewert hat wird der Compiler Ihnen einen Fehler anzeigen und das Programm kann nicht ausgeführt werden. Sie können return auch an mehreren Stellen innerhalb der Funktion nutzen. Das kann z.B. dann nützlich sein wenn Sie einen bestimmten Eingangswert erwarten oder unter bestimmten Bedingungen die Funktion vorzeitig abbrechen oder beenden möchten.
Schauen wir uns hierzu ein Beispiel an in dem wir nur eine Berechnung zulassen wenn einer der beiden Faktoren nicht dem Wert „2“ entspricht. Sollte einer der beiden Werte die „2“ sein so beenden wir die Funktion und geben als Ergebnis „0“ zurück. Den Rückgabewert prüfen wir im Anschluss in einer Kontrollstruktur. Sollte das Ergebnis „0“ sein geben wir aus das die eingehenden Daten fehlerhaft sind.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
func multipliziere(faktorA: Int, faktorB: Int) -> Int { if faktorA == 2 || faktorB == 2 { return 0 } var produkt = faktorA * faktorB return produkt } var wertX: Int = multipliziere(1,2) if wertX == 0 { println("Der Wert 2 kann nicht multipliziert werden") } |
Die Funktion selbst wird so in der freien Wildbahn sicherlich keinen Sinn machen, aber es ist ein einfaches Beispiel an dem man sehen kann was mit Swift alles möglich ist.
Benannte Parameter
Wer von Ihnen bereits mit Objective-C Erfahrung hat, kennt benannte Parameter bereits. Benannte Parameter ermöglichen es uns Parameternamen bei Funktionsaufrufen anzuzeigen. Das ganze hat einen gewaltigen Vorteil, der bereits Objective-C zu einer Sprache gemacht hat die so einfach zu lesen ist wie ein Buch. Dafür muss man aber verstehen was benannte Parameter sind und wie man das ganze ließt.
In Swift ist das ganze optisch deutlich eleganter, da Swift selbst sich vom Syntax eher an klassischen Programmiersprachen orientiert. Objective-C ist eher ein einzigartige Syntax.
Werfen wir einen Blick auf dieses Beispiel.
1 2 3 4 5 |
func multipliziere(#faktorA: Int, #faktorB: Int) -> Int { return faktorA * faktorB } var produkt = multipliziere(faktorA: 2, faktorB: 4) |
In unserem Funktionskopf sehen wir bei den Parameternamen die wir innerhalb der Funktion nutzen eine Raute „#“. Diese sorgte dafür das die Parameternamen beim Funktionsaufruf angezeigt werden. Bei der Betrachtung des Funktionsaufrufes multipliziere(faktorA: 2, faktorB: 4) haben wir vor unseren Zahlen „2“ und „4“ jetzt die Parameternamen stehen, getrennt zum Wert mit einem Doppelpunkt.
Sollten wir die „#“ bei einem der Parameter weglassen, zum Beispiel bei faktorB so würde der Funktionsaufruf so aussehen: multipliziere(faktorA: 2, 4). Das ganze sieht jetzt aber nicht mehr schön und sinnvoll aus.
Im Moment ist der Funktionsaufruf noch nicht wirklich optimal zum lesen. Swift bietet uns daher die Möglichkeit zu definieren wie der Parametername nach aussen aussieht, ohne das der Name innerhalb der Funktion abgeändert werden muss. Schauen wir uns folgende Schreibweise an.
1 2 3 4 5 |
func multipliziere(#faktorA: Int, mitFaktorB faktorB: Int) -> Int { return faktorA * faktorB } var produkt = multipliziere(faktorA: 2, mitFaktorB: 4) |
Statt einer # schreiben wir einfach den Namen der öffentlich sichtbar sein soll. In unserem Fall ist das
mitFaktorB. Wie lesen wir das ganze jetzt?
Definiere die Variable
Produkt und weise ihr den Rückgabewert des Funktionsaufrufes „multipliziere faktorA mitFaktorB“ zu.
Wie geht es weiter?
Mit dem Wissen über Funktionen nähern wir uns langsam dem Ende des Grundwissens der prozeduralen Programmierung mit Swift. In unserer nächsten Lektion über Funktionen schauen wir uns Variadics, Tuples und optionale Parameter an. Mit Funktionen haben wir den wichtigsten Grundstein gelegt damit wir bald mit Klassen und Objekten arbeiten können.
Es ist sehr wichtig Funktionen zu verinnerlichen da sie die Grundlage bilden um mit den Systembibliotheken von OS X und iOS zu kommunizieren. Mit ein wenig Übung und Routine werden Sie die Syntax aber bald verinnerlicht haben!
3 Comments
Die Abkürzung # wurde aus Swift entfernt. Will man den Variablennamen als Label verwenden, muss man ihn doppelt eingeben.
Beispiel:
1 func multipliziere(faktorA faktorA: Int, mitFaktorB faktorB: Int) -> Int {
es gibt in swift kein println mehr
es gibt nur noch print
Korrekt! =)