Kotlin Bootcamp für Programmers 3: Functions

Dieses Codelab ist Teil des Kotlin-Bootcamps für Programmierer. Sie profitieren von diesem Kurs, wenn Sie nacheinander die Codelabs durcharbeiten. Abhängig von Ihrem Wissen können Sie möglicherweise einige Abschnitte überfliegen. Dieser Kurs richtet sich an Programmierer, die eine objektorientierte Sprache kennen und Kotlin lernen möchten.

Einführung

In diesem Codelab erstellen Sie ein Kotlin-Programm. Es enthält Informationen zu Funktionen in Kotlin, darunter Standardwerte für Parameter, Filter, Lambdas und kompakte Funktionen.

Anstatt eine einzige Beispiel-App zu entwickeln, sollten die Lektionen in diesem Kurs auf Ihrem Wissen aufbauen. Sie sind aber unabhängig und können die einzelnen Abschnitte überfliegen. In vielen Beispielen sehen Sie ein Aquarium. Wenn Sie die ganze Geschichte des Aquariums sehen möchten, sollten Sie sich den Kotlin Bootcamp für Programmers Udacity ansehen.

Was Sie bereits wissen sollten

  • Moderne, objektorientierte, statisch programmierte Programmiersprache
  • In Programmen mit Klassen, Methoden und Ausnahmebehandlung in mindestens einer Sprache programmieren
  • Wie Sie mit Kotlin mit REPL (Read-Eval-Print Loop) in IntelliJ IDEA arbeiten
  • Grundlagen von Kotlin, einschließlich Typen, Operatoren und Loops

Dieses Codelab richtet sich an Programmierer, die eine objektorientierte Sprache kennen und mehr über Kotlin erfahren möchten.

Lerninhalte

  • Programm mit einer main()-Funktion und Argumenten in IntelliJ IDEA erstellen
  • Standardwerte und kompakte Funktionen verwenden
  • Filter für Listen anwenden
  • So erstellen Sie einfache Lambdas und übergeordnete Funktionen

Aufgaben

  • Gemeinsam mit dem REPL-Code testen.
  • Mit IntelliJ IDEA grundlegende Kotlin-Programme erstellen

In dieser Aufgabe erstellen Sie ein Kotlin-Programm, erfahren mehr über die Funktion main() und erfahren, wie Sie Argumente über die Befehlszeile an ein Programm übergeben können.

Vielleicht erinnern Sie sich an die printHello()-Funktion, die Sie in einem vorherigen Codelab in den REPL-Code eingegeben haben:

fun printHello() {
    println ("Hello World")
}

printHello()
⇒ Hello World

Sie definieren Funktionen mit dem Keyword fun, gefolgt vom Namen der Funktion. Wie bei anderen Programmiersprachen sind die Klammern () für Funktionsargumente, falls vorhanden. Klammern „{}“ setzen den Code für die Funktion in geschweiften Klammern. Für diese Funktion gibt es keinen Rückgabetyp, da sie nichts zurückgibt.

Schritt 1: Kotlin-Datei erstellen

  1. Öffnen Sie IntelliJ IDEA.
  2. Im Bereich Projekt links in IntelliJ IDEA wird eine Liste Ihrer Projektdateien und Ordner angezeigt. Klicken Sie mit der rechten Maustaste unter Hello Kotlin auf den Ordner src. Ihr sollte bereits das Hello Kotlin-Projekt aus dem vorherigen Codelab haben.
  3. Wähle Neu > Kotlin-Datei/Klasse aus.
  4. Lassen Sie Kind als File und nennen Sie die Datei Hello.
  5. Klicken Sie auf OK.

Im Ordner src befindet sich jetzt eine Datei mit dem Namen Hello.kt.

Schritt 2: Code hinzufügen und Programm ausführen

  1. Wie bei anderen Sprachen gibt auch die Kotlin-Funktion main() den Einstiegspunkt für die Ausführung an. Alle Befehlszeilenargumente werden als String-Array übergeben.

    Geben Sie den folgenden Code in die Datei Hello.kt ein oder fügen Sie ihn ein:
fun main(args: Array<String>) {
    println("Hello, world!")
}

Wie Ihre vorherige printHello()-Funktion hat diese Funktion keine return-Anweisung. Jede Funktion in Kotlin gibt etwas zurück, auch wenn nichts anderes festgelegt ist. Eine Funktion wie diese main() gibt also den Typ kotlin.Unit zurück. Dies ist eine Art von Kotlin, bei der kein Wert angegeben wird.

  1. Klicken Sie auf das grüne Dreieck links neben der Funktion main(), um das Programm auszuführen. Wählen Sie im Menü Run 'HelloKt' aus.
  2. IntelliJ IDEA kompiliert das Programm und führt es aus. Die Ergebnisse werden unten in einem Log-Bereich angezeigt.

Schritt 3: Argumente an main() übergeben

Da Sie Ihr Programm über IntelliJ IDEA und nicht über die Befehlszeile ausführen, müssen Sie Argumente für das Programm etwas anders angeben.

  1. Wählen Sie Run > Edit Configurations aus. Das Fenster Run/Debug Configurations (Ausführungs-/Fehlerbehebungskonfigurationen) wird geöffnet.
  2. Geben Sie Kotlin! in das Feld Programmargumente ein.
  3. Klicken Sie auf OK.

Schritt 4: Code zur Verwendung einer Stringvorlage ändern

Mit einer Stringvorlage wird eine Variable oder ein Ausdruck in einen String eingefügt und $ gibt an, dass ein Teil des Strings eine Variable oder ein Ausdruck ist. Legt den Ausdruck in geschweiften Klammern {} fest, falls vorhanden.

  1. Ändern Sie in Hello.kt die Begrüßungsnachricht so, dass das erste Argument, das an das Programm übergeben wird, args[0] statt "world" verwendet wird.
fun main(args: Array<String>) {
    println("Hello, ${args[0]}")
}
  1. Führen Sie das Programm aus. Die Ausgabe enthält das von Ihnen angegebene Argument.
⇒ Hello, Kotlin!

In dieser Aufgabe erfahren Sie, warum fast alles in Kotlin einen Wert hat und warum das so nützlich ist.

In einigen anderen Sprachen gibt es Anweisungen, bei denen es sich um Codezeilen handelt, die keinen Wert haben. In Kotlin ist fast alles ein Ausdruck und hat einen Wert, auch wenn dieser Wert kotlin.Unit ist.

  1. Schreiben Sie in Hello.kt den Code in main(), um ein println()-Element der Variablen isUnit zuzuweisen und sie zu drucken. println() gibt keinen Wert zurück, sodass kotlin.Unit zurückgegeben wird.
// Will assign kotlin.Unit
val isUnit = println("This is an expression")
println(isUnit)
  1. Führe dein Programm aus. Der erste println() gibt den String "This is an expression" aus. Die zweite println() gibt den Wert der ersten println()-Anweisung aus, also kotlin.Unit.
⇒ This is an expression
kotlin.Unit
  1. Deklarieren Sie eine val namens temperature und initialisieren Sie sie auf 10.
  2. Deklarieren Sie eine weitere val namens isHot und weisen Sie den Rückgabewert einer if/else-Anweisung zu isHot zu, wie im folgenden Code zu sehen ist. Da es sich um einen Ausdruck handelt, können Sie den Wert des Ausdrucks if sofort verwenden.
val temperature = 10
val isHot = if (temperature > 50) true else false
println(isHot)
⇒ false
  1. Wert eines Ausdrucks in einer Stringvorlage verwenden Füge einen Code hinzu, um die Temperatur zu überprüfen, um zu ermitteln, ob ein Fisch sicher oder zu warm ist. Führe dann dein Programm aus.
val temperature = 10
val message = "The water temperature is ${ if (temperature > 50) "too warm" else "OK" }."
println(message)
⇒ The water temperature is OK.

In dieser Aufgabe erfahren Sie mehr über Funktionen in Kotlin und über den sehr hilfreichen bedingten when-Ausdruck.

Schritt 1: Funktionen erstellen

In diesem Schritt stellen Sie einige der gelernten Funktionen zusammen und erstellen sie mit verschiedenen Typen. Sie können den Inhalt von Hello.kt durch diesen neuen Code ersetzen.

  1. Schreiben Sie eine Funktion namens feedTheFish(), die randomDay() aufruft, um einen zufälligen Wochentag zu erhalten. Mit einer Stringvorlage können Sie eine food drucken, die an diesem Tag als Fisch ausgegeben wird. Vorerst essen die Fische jeden Tag dasselbe Essen.
fun feedTheFish() {
    val day = randomDay()
    val food = "pellets"
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}
  1. Schreiben Sie die randomDay()-Funktion, um einen zufälligen Tag aus einem Array auszuwählen und zurückzugeben.

Die Funktion nextInt() verwendet ein Ganzzahl-Limit, das die Anzahl von Random() bis 6 bis 6 begrenzt, um dem week-Array zu entsprechen.

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
            "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}
  1. Die Funktionen Random() und nextInt() sind in java.util.* definiert. Fügen Sie oben in der Datei den erforderlichen Import hinzu:
import java.util.*    // required import
  1. Führen Sie Ihr Programm aus und prüfen Sie die Ausgabe.
⇒ Today is Tuesday and the fish eat pellets

Schritt 2: Wann-Ausdruck verwenden

Wenn du dies noch genauer darstellst, ändere den Code, um mit einem when-Ausdruck unterschiedliche Lebensmittel für verschiedene Tage auszuwählen. Die when-Anweisung ähnelt in anderen Programmiersprachen der switch, aber when wird automatisch am Ende jeder Zweigstelle unterbrochen. Außerdem wird so sichergestellt, dass Ihr Code alle Zweige abdeckt, wenn Sie eine Aufzählung prüfen.

  1. Fügen Sie in Hello.kt eine Funktion namens „fishFood()“ hinzu, die einen Tag als String verwendet und das Fischfutter des Tages als String zurückgibt. Mithilfe von when() wird den Fischen jeden Tag ein bestimmtes Essen serviert. Führen Sie Ihr Programm mehrmals aus, um verschiedene Ausgaben zu sehen.
fun fishFood (day : String) : String {
    var food = ""
    when (day) {
        "Monday" -> food = "flakes"
        "Tuesday" -> food = "pellets"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Saturday" -> food = "lettuce"
        "Sunday" -> food = "plankton"
    }
    return food
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)

    println ("Today is $day and the fish eat $food")
}
⇒ Today is Thursday and the fish eat granules
  1. Fügen Sie dem when-Ausdruck mit else einen Standardzweig hinzu. Um zu testen, ob der Standardwert manchmal in deinem Programm verwendet wird, entferne die Zweige Tuesday und Saturday.

    Mit einem Standardzweig wird sichergestellt, dass food vor der Rückgabe einen Wert erhält. Daher muss dieser nicht mehr initialisiert werden. Da der Code einem String jetzt nur einmal food zuweist, können Sie food mit val statt mit var deklarieren.
fun fishFood (day : String) : String {
    val food : String
    when (day) {
        "Monday" -> food = "flakes"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Sunday" -> food = "plankton"
        else -> food = "nothing"
    }
    return food
}
  1. Da jeder Ausdruck einen Wert hat, können Sie diesen Code etwas prägnanter definieren. Gibt den Wert des Ausdrucks when direkt zurück und entferne die Variable food. Der Wert des Ausdrucks when ist der Wert des letzten Ausdrucks des Zweigs, der die Bedingung erfüllt hat.
fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

Die endgültige Version deines Programms sieht ungefähr so aus:

import java.util.*    // required import

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}

fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}

In dieser Aufgabe lernen Sie die Standardwerte für Funktionen und Methoden kennen. Außerdem lernen Sie kompakte Funktionen kennen, mit denen Sie Ihren Code prägnanter und besser lesbar machen können. Außerdem können Sie die Anzahl der Codepfade für Tests reduzieren. Kompakte Funktionen werden auch als Funktionen mit einem Ausdruck bezeichnet.

Schritt 1: Standardwert für einen Parameter erstellen

In Kotlin können Sie Argumente nach Parameternamen übergeben. Sie können auch Standardwerte für Parameter angeben. Wenn ein Argument vom Aufrufer bereitgestellt wird, wird der Standardwert verwendet. Wenn Sie später Methoden (Mitgliederfunktionen) schreiben, bedeutet dies, dass keine übermäßigen Versionen derselben Methode geschrieben werden.

  1. Schreiben Sie in Hello.kt eine swim()-Funktion mit einem String-Parameter namens speed, der die Geschwindigkeit des Fisches ausgibt. Der Parameter speed hat den Standardwert "fast".
fun swim(speed: String = "fast") {
   println("swimming $speed")
}
  1. Rufen Sie in der Funktion main() drei Funktionen auf: Rufen Sie zuerst die Funktion mit der Standardeinstellung auf. Rufen Sie dann die Funktion auf und übergeben Sie den Parameter speed ohne Namen. Rufen Sie dann die Funktion auf, indem Sie den Parameter speed benennen.
swim()   // uses default speed
swim("slow")   // positional argument
swim(speed="turtle-like")   // named parameter
⇒ swimming fast
swimming slow
swimming turtle-like

Schritt 2: Erforderliche Parameter hinzufügen

Wenn für einen Parameter kein Standardwert angegeben ist, muss das entsprechende Argument immer übergeben werden.

  1. Schreiben Sie in Hello.kt eine shouldChangeWater()-Funktion, die drei Parameter annimmt: day, temperature und eine dirty-Ebene. Die Funktion gibt true zurück, wenn das Wasser geändert werden soll. Dies ist dann der Fall, wenn es sonntags liegt, die Temperatur zu hoch ist oder das Wasser zu stark schmutzig ist. Der Wochentag ist erforderlich, die Standardtemperatur ist jedoch 22 und die Standardtemperatur ist 20.

    Verwende einen when-Ausdruck ohne Argument, das in Kotlin als eine Reihe von if/else if-Prüfungen fungiert.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        temperature > 30 -> true
        dirty > 30 -> true
        day == "Sunday" ->  true
        else -> false
    }
}
  1. Rufen Sie shouldChangeWater() bei feedTheFish() an und geben Sie den Tag an. Für den Parameter day gibt es keinen Standardwert. Sie müssen also ein Argument angeben. Für die anderen beiden Parameter von shouldChangeWater() gibt es Standardwerte. Sie müssen also keine Argumente dafür übergeben.
fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
    println("Change water: ${shouldChangeWater(day)}")
}
=> Today is Thursday and the fish eat granules
Change water: false

Schritt 3: Kompakte Funktionen erstellen

Der when-Ausdruck, den Sie im vorherigen Schritt geschrieben haben, fasst viel Logik in einer kleinen Codemenge zusammen. Wenn Sie die Elemente etwas entpacken möchten oder die Bedingungen für die Prüfung komplizierter sind, können Sie einige benannte lokale Variablen verwenden. Hierfür bietet Kotlin eine kompakte Funktion.

Kompakte Funktionen oder Funktionen mit einem Ausdruck sind ein gängiges Muster in Kotlin. Wenn eine Funktion die Ergebnisse eines einzelnen Ausdrucks zurückgibt, können Sie den Text der Funktion nach einem =-Symbol angeben, die geschweiften Klammern {} weglassen und return weglassen.

  1. Fügen Sie in Hello.kt kompakte Funktionen hinzu, um die Bedingungen zu testen.
fun isTooHot(temperature: Int) = temperature > 30

fun isDirty(dirty: Int) = dirty > 30

fun isSunday(day: String) = day == "Sunday"
  1. Ändern Sie shouldChangeWater(), um die neuen Funktionen aufzurufen.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        isTooHot(temperature) -> true
        isDirty(dirty) -> true
        isSunday(day) -> true
        else  -> false
    }
}
  1. Führe dein Programm aus. Die Ausgabe von println() sollte mit der von shouldChangeWater() übereinstimmen, bevor du die kompakten Funktionen verwendet hast.

Standardwerte

Der Standardwert für einen Parameter muss kein Wert sein. Es kann sich auch um eine andere Funktion handeln, wie im folgenden Teilbeispiel gezeigt:

fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = getDirtySensorReading()): Boolean {
    ...

In dieser Aufgabe lernen Sie etwas über Filter in Kotlin. Filter sind ein praktisches Mittel, um auf der Grundlage einer Bedingung einen Teil einer Liste zu erhalten.

Schritt 1: Filter erstellen

  1. Definieren Sie auf Hello.kt eine Liste von Aquariumdekorationen auf oberster Ebene mit listOf(). Sie können den Inhalt von Hello.kt ersetzen.
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
  1. Erstellen Sie eine neue main()-Funktion mit einer Zeile, um nur die Dekorationen zu drucken, die mit dem Buchstaben 'p' beginnen. Der Code für die Filterbedingung ist in geschweiften Klammern {} gesetzt. In it wird die Position des Elements als Schleife bezeichnet. Falls der Ausdruck true zurückgibt, ist das Element eingeschlossen.
fun main() {
    println( decorations.filter {it[0] == 'p'})
}
  1. Wenn Sie das Programm ausführen, wird im Fenster Run (Ausführen) die folgende Ausgabe angezeigt:
⇒ [pagoda, plastic plant]

Schritt 2: Flüchtige und Lazy-Filter vergleichen

Wenn Sie mit Filtern in anderen Sprachen vertraut sind, fragen Sie sich vielleicht, ob Filter in Kotlin eilig oder lazy sind. Wird die Ergebnisliste sofort oder beim Zugriff auf die Liste erstellt? In Kotlin geschieht das ganz nach Bedarf. Standardmäßig ist filter offen und jedes Mal, wenn Sie den Filter verwenden, wird auch eine Liste erstellt.

Um den Filter als Lazy zu konfigurieren, können Sie eine Sequence verwenden. Dabei handelt es sich um eine Sammlung, mit der Sie nur jeweils ein Element ansehen können, beginnend am Anfang und Ende. Praktischerweise ist dies genau die API, die ein Lazy-Filter benötigt.

  1. Ändern Sie in Hello.kt den Code, um die gefilterte Liste einer Variablen mit dem Namen eager zuzuweisen und sie dann auszudrucken.
fun main() {
    val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

    // eager, creates a new list
    val eager = decorations.filter { it [0] == 'p' }
    println("eager: " + eager)
  1. Unter diesem Code kannst du den Filter mit einer Sequence und einem asSequence() auswerten. Weisen Sie die Sequenz einer Variablen namens filtered zu und drucken Sie sie aus.
   // lazy, will wait until asked to evaluate
    val filtered = decorations.asSequence().filter { it[0] == 'p' }
    println("filtered: " + filtered)

Wenn Sie die Filterergebnisse als Sequence zurückgeben, wird die Variable filtered keine neue Liste enthalten, sondern eine Sequence der Listenelemente sowie das Wissen über den Filter, die auf diese Elemente angewendet werden sollen. Bei jedem Zugriff auf Elemente von Sequence wird der Filter angewendet und das Ergebnis wird Ihnen zurückgegeben.

  1. Erzwingen Sie die Auswertung der Sequenz, indem Sie sie mit toList() in List konvertieren. Drucken Sie das Ergebnis aus.
    // force evaluation of the lazy list
    val newList = filtered.toList()
    println("new list: " + newList)
  1. Führen Sie Ihr Programm aus und beobachten Sie die Ausgabe.
⇒ eager: [pagoda, plastic plant]
filtered: kotlin.sequences.FilteringSequence@386cc1c4
new list: [pagoda, plastic plant]

Zur Visualisierung des Problems mit der Sequence- und der Lazy-Bewertung verwenden Sie die Funktion map(). Mit der map()-Funktion lässt sich jedes Element in der Sequenz leicht transformieren.

  1. Führen Sie mit derselben decorations-Liste wie oben eine Transformation mit map() durch, die nichts tut, und gibt nur das übergebene Element zurück. Fügen Sie einen println() hinzu, der immer dann angezeigt wird, wenn auf ein Element zugegriffen wird. Weisen Sie die Sequenz dann einer Variablen namens lazyMap zu.
    val lazyMap = decorations.asSequence().map {
        println("access: $it")
        it
    }
  1. Du kannst lazyMap drucken, das erste Element von lazyMap mit first() drucken und lazyMap, die in ein List umgewandelt wurden.
    println("lazy: $lazyMap")
    println("-----")
    println("first: ${lazyMap.first()}")
    println("-----")
    println("all: ${lazyMap.toList()}")
  1. Führen Sie Ihr Programm aus und beobachten Sie die Ausgabe. Beim Drucken von lazyMap wird einfach ein Verweis auf die Sequence gedruckt – die innere println() wird nicht aufgerufen. Wenn das erste Element gedruckt wird, wird nur auf das erste Element zugegriffen. Wenn Sie Sequence in List konvertieren, können Sie auf alle Elemente zugreifen.
⇒ lazy: kotlin.sequences.TransformingSequence@5ba23b66
-----
access: rock
first: rock
-----
access: rock
access: pagoda
access: plastic plant
access: alligator
access: flowerpot
all: [rock, pagoda, plastic plant, alligator, flowerpot]
  1. Erstellen Sie eine neue Sequence mit dem ursprünglichen Filter, bevor Sie map anwenden. Drucken Sie das Ergebnis aus.
    val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
        println("access: $it")
        it
    }
    println("-----")
    println("filtered: ${ lazyMap2.toList() }")
  1. Führen Sie Ihr Programm aus und beobachten Sie die zusätzliche Ausgabe. Wie beim Abrufen des ersten Elements werden auch die inneren println() nur für die Elemente aufgerufen, auf die zugegriffen wird.
⇒
-----
access: pagoda
access: plastic plant
filtered: [pagoda, plastic plant]

In dieser Aufgabe erhalten Sie eine Einführung zu Lambdas und höheren Funktionen in Kotlin.

Lambdas

Zusätzlich zu den traditionellen benannten Funktionen unterstützt Kotlin Lambdas. Ein Lambda ist ein Ausdruck, der eine Funktion erstellt. Doch anstatt eine benannte Funktion zu deklarieren, deklarieren Sie eine Funktion, die keinen Namen hat. Dazu gehört unter anderem, dass der Lambda-Ausdruck jetzt als Daten weitergegeben werden kann. In anderen Sprachen werden Lambdas als anonyme Funktionen, Funktionsliterale oder ähnliche Namen bezeichnet.

Höhere Funktionen

Sie können eine übergeordnete Funktion erstellen, indem Sie eine Lammda an eine andere Funktion übergeben. In der vorherigen Aufgabe haben Sie eine übergeordnete Funktion erstellt: filter. Sie haben den folgenden Lambda-Ausdruck an filter übergeben, um diese Bedingung zu prüfen:
{it[0] == 'p'}

map ist auch eine übergeordnete Funktion und das Lambda, das Sie an sie übergeben haben, war die Transformation, die angewendet werden sollte.

Schritt 1: Weitere Informationen zu Lambdas

  1. Wie benannte Funktionen können auch Lambdas Parameter haben. Für Lambdas befinden sich die Parameter (und gegebenenfalls deren Typen) links neben dem sogenannten Funktionspfeil ->. Der auszuführende Code befindet sich rechts neben dem Funktionspfeil. Nachdem das Lambda einer Variable zugewiesen wurde, kann es wie eine Funktion aufgerufen werden.

    Probieren Sie diesen Code mit der REPL (Tools > Kotlin > Kotlin REPL) aus:
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
⇒ 10

In diesem Beispiel gibt das Lambda ein Int mit dem Namen dirty und gibt dirty / 2 zurück. Weil Filter herausgefiltert werden

  1. Die Kotlin-Syntax für Funktionstypen steht in engem Zusammenhang mit ihrer Syntax für Lambdas. Verwenden Sie diese Syntax, um eine Variable, die eine Funktion enthält, sauber zu deklarieren:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }

Im Code steht Folgendes:

  • Erstellen Sie eine Variable namens waterFilter.
  • waterFilter kann eine beliebige Funktion sein, die ein Int verwendet und ein Int zurückgibt.
  • Weisen Sie waterFilter ein Lambda zu.
  • Das Lambda gibt den Wert des Arguments dirty zurück, geteilt durch 2.

Hinweis: Du musst den Typ des Lambda-Arguments nicht mehr angeben. Der Typ wird anhand der Typinferenz berechnet.

Schritt 2: Funktion mit höherer Reihenfolge erstellen

Bislang sehen die Beispiele für Lambdas hauptsächlich nach Funktionen. Das wirkliche Potenzial von Lambdas besteht darin, damit höherwertige Funktionen zu erstellen. Das Argument für eine Funktion ist eine andere Funktion.

  1. Schreiben Sie eine Funktion mit höherer Priorität. Hier sehen Sie ein grundlegendes Beispiel, eine Funktion, die zwei Argumente verwendet. Das erste Argument ist eine Ganzzahl. Das zweite Argument ist eine Funktion, die eine Ganzzahl übernimmt und eine Ganzzahl zurückgibt. Probier es in der REPL aus.
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
   return operation(dirty)
}

Der Text des Codes ruft die Funktion auf, die als zweites Argument übergeben wurde, und übergibt das erste Argument an sie.

  1. Um diese Funktion aufzurufen, müssen Sie eine Ganzzahl und eine Funktion übergeben.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
⇒ 15

Die Funktion, die Sie weitergeben, muss keine Lambda sein, sondern kann eine reguläre benannte Funktion sein. Wenn Sie das Argument als reguläre Funktion angeben möchten, verwenden Sie den Operator ::. So weiß Kotlin, dass Sie die Funktionsreferenz als Argument übergeben und nicht versuchen, die Funktion aufzurufen.

  1. Versuchen Sie, eine reguläre benannte Funktion an updateDirty() zu übergeben.
fun increaseDirty( start: Int ) = start + 1

println(updateDirty(15, ::increaseDirty))
⇒ 16
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)
⇒ 42
  • Wenn Sie eine Kotlin-Quelldatei in IntelliJ IDEA erstellen möchten, beginnen Sie mit einem Kotlin-Projekt.
  • Klicken Sie auf das grüne Dreieck neben der Funktion main(), um ein Programm in IntelliJ IDEA zu kompilieren und auszuführen. Die Ausgabe wird unten in einem Protokollfenster angezeigt.
  • Geben Sie in IntelliJ IDEA Befehlszeilenargumente an, die an die Funktion main() unter Konfigurationen ausführen und bearbeiten übergeben werden sollen.
  • Fast alles in Kotlin hat einen Wert. Du kannst diese Tatsache verwenden, um deinen Code prägnanter zu gestalten. Verwende dazu den Wert von if oder when als Ausdruck oder Rückgabewert.
  • Bei Standardargumenten ist es nicht erforderlich, mehrere Versionen einer Funktion oder Methode zu verwenden. Beispiel:
    fun swim(speed: String = "fast") { ... }
  • Mit kompakten Funktionen bzw. Funktionen mit einzelnen Ausdrücken kann der Code besser lesbar werden. Beispiel:
    fun isTooHot(temperature: Int) = temperature > 30
  • Du hast einige Grundlagen zu Filtern gelernt, bei denen Lambda-Ausdrücke verwendet werden. Beispiel:
    val beginsWithP = decorations.filter { it [0] == 'p' }
  • Ein Lambda-Ausdruck ist ein Ausdruck, der eine unbenannte Funktion macht. Lambda-Ausdrücke sind zwischen geschweiften Klammern {} definiert.
  • In einer höheren Reihenfolge übergeben Sie eine Funktion wie einen Lambda-Ausdruck als Daten an eine andere Funktion. Beispiel:
    dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}

In dieser Lektion gibt es viel zu sehen, vor allem, wenn man Lavdas nicht kennt. In einer späteren Lektion gehen wir noch einmal auf Lambdas und übergeordnete Funktionen zurück.

Kotlin-Dokumentation

Wenn Sie weitere Informationen zu einem Thema in diesem Kurs benötigen oder nicht mehr weiterkommen, ist https://kotlinlang.org der beste Ausgangspunkt.

Kotlin-Anleitungen

Auf der Website https://try.kotlinlang.org finden Sie umfassende Anleitungen mit dem Namen Kotlin Koans, einem webbasierten Interpreter und eine umfassende Referenz mit Beispielen.

Udacity-Kurs

Informationen zum Udacity-Kurs zu diesem Thema finden Sie im Kotlin-Bootcamp für Programmierer.

IntelliJ IDEA

Die Dokumentation für IntelliJ IDEA finden Sie auf der JetBrains-Website.

In diesem Abschnitt werden mögliche Hausaufgaben für Schüler oder Studenten aufgeführt, die an diesem von einem Kursleiter geleiteten Codelab arbeiten. Die Lehrkraft kann Folgendes tun:

  • Bei Bedarf können Sie die entsprechenden Aufgaben zuweisen.
  • Schülern mitteilen, wie sie Aufgaben für die Aufgabe abgeben
  • Benoten Sie die Hausaufgaben.

Lehrkräfte können diese Vorschläge so oft oder so oft verwenden, wie sie möchten. anderen Aufgaben können sie nach Belieben zugewiesen werden.

Wenn Sie alleine an diesem Codelab arbeiten, können Sie Ihr Wissen mit diesen Hausaufgaben testen.

Diese Fragen beantworten

Frage 1

Die Funktion contains(element: String) gibt true zurück, wenn der String element im aufgerufenen String enthalten ist. Wie wird der folgende Code ausgegeben?

val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

println(decorations.filter {it.contains('p')})

[pagoda, plastic, plant]

[pagoda, plastic plant]

[pagoda, plastic plant, flowerpot]

[rock, alligator]

Frage 2

Welcher der Parameter ist in der folgenden Funktionsdefinition erforderlich?
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20, numDecorations: Int = 0): Boolean {...}

numDecorations

dirty

day

temperature

Frage 3

Sie können eine reguläre benannte Funktion (nicht das Ergebnis eines Aufrufs) an eine andere Funktion übergeben. Wie würdest du increaseDirty( start: Int ) = start + 1 an updateDirty(dirty: Int, operation: (Int) -> Int) übergeben?

updateDirty(15, &increaseDirty())

updateDirty(15, increaseDirty())

updateDirty(15, ("increaseDirty()"))

updateDirty(15, ::increaseDirty)

Fahren Sie mit der nächsten Lektion fort: 4. Klassen und Objekte

Eine Übersicht über den Kurs, einschließlich Links zu anderen Codelabs, findest du im "Kotlin Bootcamp für Programmierer: Kurs.