Stufe 2Sprachkern · Lektion 8 von 34
Funktionen und Methoden
Methoden definieren Sie mit def, Funktionen sind Werte, die man herumreichen kann – und Operatoren wie + sind in Scala einfach Methoden mit ungewöhnlichem Namen. Diese Lektion zeigt, wie das zusammenpasst.
Methoden mit def
def flaeche(breite: Double, hoehe: Double): Double =
breite * hoehe
flaeche(3, 4.5) // 13.5Jeder Parameter braucht einen Typ, der Rückgabetyp ist optional, aber bei öffentlichen Methoden empfohlen. Der Rumpf ist ein Ausdruck, dessen Wert zurückgegeben wird – ein return ist nicht nötig.
Standardwerte und benannte Argumente
def gruss(name: String, anrede: String = "Hallo", ausrufe: Int = 1): String =
s"$anrede, $name" + "!" * ausrufe
gruss("Ada") // Hallo, Ada!
gruss("Ada", ausrufe = 3) // Hallo, Ada!!!
gruss(anrede = "Servus", name = "Alan")Standardwerte ersparen viele überladene Varianten einer Methode. Benannte Argumente machen Aufrufe mit mehreren gleichartigen Parametern lesbarer: verschiebe(x = 10, y = -4) ist eindeutiger als verschiebe(10, -4).
Variable Argumentanzahl
def summe(zahlen: Int*): Int = zahlen.sum
summe(1, 2, 3) // 6
val liste = List(4, 5)
summe(liste*) // 9 – Liste „auspacken“Funktionen als Werte
Neben Methoden gibt es Funktionswerte. Sie haben einen Typ wie Int => Int („von Int nach Int“) und lassen sich in Variablen speichern:
val verdoppeln: Int => Int = x => x * 2
val addieren = (a: Int, b: Int) => a + b
verdoppeln(21) // 42
addieren(2, 3) // 5Der Ausdruck x => x * 2 heißt anonyme Funktion oder Lambda. Besonders nützlich sind sie als Argumente anderer Methoden:
val zahlen = List(1, 2, 3, 4)
zahlen.map(x => x * 2) // List(2, 4, 6, 8)
zahlen.map(_ * 2) // dasselbe, kürzer
zahlen.filter(_ % 2 == 0) // List(2, 4)Der Unterstrich steht für „den jeweiligen Parameter“. Er eignet sich für kurze Ausdrücke; sobald ein Parameter zweimal vorkommt, brauchen Sie wieder einen Namen.
Methoden lassen sich ebenfalls übergeben. Scala wandelt sie automatisch in Funktionswerte um:
def istGerade(n: Int): Boolean = n % 2 == 0
zahlen.filter(istGerade) // List(2, 4)Funktionen, die Funktionen liefern
def multiplikator(faktor: Int): Int => Int = x => x * faktor
val mal3 = multiplikator(3)
mal3(14) // 42Die zurückgegebene Funktion „merkt“ sich den Wert von faktor. So etwas nennt man Closure. Funktionen, die Funktionen annehmen oder liefern, heißen Funktionen höherer Ordnung – ein Grundbaustein der funktionalen Programmierung.
Mehrere Parameterlisten
Eine Methode kann mehrere Parameterlisten haben. Das nennt man Currying:
def wiederhole(n: Int)(aktion: => Unit): Unit =
for _ <- 1 to n do aktion
wiederhole(3) {
println("Scala")
}Der Parameter aktion: => Unit ist ein By-Name-Parameter: Der übergebene Block wird nicht vorab ausgewertet, sondern bei jedem Zugriff neu. Zusammen mit der zweiten Parameterliste entsteht so etwas, das aussieht wie eine eingebaute Kontrollstruktur. Auf diese Weise sind viele Bibliotheken in Scala gebaut.
Operatoren sind Methoden
In Scala gibt es keine eingebauten Operatoren im engeren Sinn. 1 + 2 ist der Aufruf der Methode + auf dem Objekt 1:
1 + 2 // entspricht 1.+(2)
"abc" * 2 // entspricht "abc".*(2), ergibt "abcabc"Eigene Klassen können genauso Operatoren definieren:
case class Geld(cent: Long):
def +(anderes: Geld): Geld = Geld(cent + anderes.cent)
override def toString = f"${cent / 100.0}%.2f €"
Geld(1999) + Geld(501) // 25,00 € bzw. 25.00 € je nach SpracheinstellungUmgekehrt lassen sich Methoden mit einem Parameter wie Operatoren aufrufen: a max b statt a.max(b). Scala 3 sieht dafür bei eigenen Methoden die Markierung infix vor (infix def plus(…)), sonst warnt der Compiler in strengeren Einstellungen. Für die meisten Methoden ist die Punktschreibweise ohnehin die lesbarere Wahl.
Extension Methods
Mit extension fügen Sie bestehenden Typen neue Methoden hinzu, ohne sie zu verändern:
extension (s: String)
def istPalindrom: Boolean =
val t = s.toLowerCase.filter(_.isLetter)
t == t.reverse
"Reliefpfeiler".istPalindrom // trueMehr über diesen Mechanismus und seine Scala-2-Vorgänger steht in der Lektion über given, using und implizite Konvertierung.