Kotlin Bootcamp für Programmer 5.2: Allgemeine Fragen

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 lernen Sie allgemeine Klassen, Funktionen und Methoden in Kotlin kennen.

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

  • Die Syntax von Funktionen und Klassen von Kotlin
  • Neue Klasse in IntelliJ IDEA erstellen und ein Programm ausführen

Lerninhalte

  • Mit allgemeinen Klassen, Methoden und Funktionen arbeiten

Aufgaben

  • Allgemeine Klasse erstellen und Einschränkungen hinzufügen
  • Typen in und out erstellen
  • Allgemeine Funktionen, Methoden und Erweiterungsfunktionen erstellen

Einführung in die allgemeine Monetarisierung

Wie bei vielen Programmiersprachen gibt es auch bei Kotlin allgemeine Typen. Mit einem generischen Typ können Sie eine Klasse generischer gestalten und dadurch eine Klasse wesentlich flexibler machen.

Angenommen, Sie haben eine MyList-Klasse mit einer Liste von Elementen implementiert. Ohne allgemeine Anzeigen müssten Sie eine neue Version von MyList für jeden Typ implementieren: eine für Double, eine für String, eine für Fish. Mit einer generischen Liste können Sie die Liste allgemein gestalten, sodass sie jede Art von Objekt enthalten kann. Damit wird der Typ als Platzhalter eingefügt, der für viele Typen passt.

Definieren Sie einen generischen Typ, indem Sie T in spitze Klammern <T> nach dem Klassennamen setzen. (Sie können einen anderen Buchstaben oder einen längeren Namen verwenden, die Konvention für einen generischen Typ ist jedoch T.)

class MyList<T> {
    fun get(pos: Int): T {
        TODO("implement")
    }
    fun addItem(item: T) {}
}

Du kannst T so beschreiben, als wäre es ein normaler Typ. Der Rückgabetyp für get() ist T und der Parameter für addItem() hat den Typ T. Allgemeine Listen sind natürlich sehr nützlich, daher ist die Klasse List in Kotlin integriert.

Schritt 1: Typhierarchie erstellen

In diesem Schritt erstellen Sie einige Klassen, die im nächsten Schritt verwendet werden sollen. Die Unterklasse wurde in einem früheren Codelab behandelt. Hier ein kurzer Überblick.

  1. Damit das Beispiel übersichtlich bleibt, erstellen Sie ein neues Paket unter src und nennen es generics.
  2. Erstellen Sie im Paket generics eine neue Datei Aquarium.kt. Damit sind die Namen ohne Konflikte neu definiert. Der Rest des Codes für dieses Codelab wird in diese Datei verschoben.
  3. Erstellen Sie eine Hierarchie der Wasserversorgungstypen. Machen Sie zuerst WaterSupply zur open-Klasse, sodass sie abgeleitet werden kann.
  4. Fügen Sie einen booleschen var-Parameter hinzu: needsProcessing. Dadurch werden automatisch änderbare Eigenschaften sowie Getter und Setter erstellt.
  5. Erstellen Sie eine Unterklasse (TapWater), die WaterSupply erweitert, und übergeben Sie true für needsProcessing, weil das Interaktionswasser Additive enthält, die für Fische schlecht sind.
  6. Definiere in TapWater eine Funktion namens addChemicalCleaners(), die nach dem Reinigen des Wassers needsProcessing auf false setzt. Die needsProcessing-Property kann von TapWater festgelegt werden, da sie standardmäßig public ist und für Unterklassen zugänglich ist. Hier ist der vollständige Code.
package generics

open class WaterSupply(var needsProcessing: Boolean)

class TapWater : WaterSupply(true) {
   fun addChemicalCleaners() {
       needsProcessing = false
   }
}
  1. Erstellen Sie zwei weitere Unterklassen von WaterSupply: FishStoreWater und LakeWater. FishStoreWater benötigt keine Verarbeitung, aber LakeWater muss mit der filter()-Methode gefiltert werden. Nach dem Filtern muss sie nicht noch einmal verarbeitet werden. Legen Sie in filter() needsProcessing = false fest.
class FishStoreWater : WaterSupply(false)

class LakeWater : WaterSupply(true) {
   fun filter() {
       needsProcessing = false
   }
}

Wenn Sie weitere Informationen benötigen, lesen Sie die vorherige Lektion zur Übernahme in Kotlin.

Schritt 2: Allgemeine Klasse erstellen

In diesem Schritt ändern Sie die Klasse Aquarium, um verschiedene Arten von Wasserbedarf zu unterstützen.

  1. Definieren Sie in Aquarium.kt eine Aquarium-Klasse mit <T> in Klammern nach dem Kursnamen.
  2. Eine unveränderbare Property „waterSupply“ vom Typ „T“ zu Aquarium hinzufügen.
class Aquarium<T>(val waterSupply: T)
  1. Schreiben Sie eine Funktion namens genericsExample(). Das ist kein Teil einer Klasse und kann daher auf der obersten Ebene der Datei platziert werden, beispielsweise der Funktion main() oder den Klassendefinitionen. Erstellen Sie in der Funktion ein Aquarium und übergeben Sie einen WaterSupply. Da der Parameter waterSupply generisch ist, müssen Sie den Typ in den spitzen Klammern <> angeben.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
}
  1. In genericsExample() können Sie mit Ihrem Code auf das Aquarium waterSupply zugreifen. Da sie vom Typ TapWater ist, können Sie addChemicalCleaners() ohne Typübertragungen aufrufen.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. Beim Erstellen des Aquarium-Objekts kannst du die spitzen Klammern und die dazwischen liegenden Elemente entfernen, weil Kotlin Typtypen enthält. Es gibt keinen Grund, TapWater beim Erstellen der Instanz zweimal zu sagen. Der Typ kann durch das Argument von Aquarium abgeleitet werden. trotzdem wird ein Aquarium des Typs TapWater erstellt.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. Wenn du wissen möchtest, was passiert, drucke needsProcessing vor und nach dem Anruf von addChemicalCleaners() aus. Unten sehen Sie die abgeschlossene Funktion.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
    aquarium.waterSupply.addChemicalCleaners()
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}
  1. Fügen Sie eine main()-Funktion hinzu, um genericsExample() aufzurufen. Führen Sie dann das Programm aus und beobachten Sie das Ergebnis.
fun main() {
    genericsExample()
}
⇒ water needs processing: true
water needs processing: false

Schritt 3: Machen Sie konkretere Angaben

Allgemein bedeutet, dass Sie fast alles übergeben können. Manchmal ist das ein Problem. In diesem Schritt machen Sie die Aquarium-Klasse spezifischer.

  1. Erstellen Sie im genericsExample() ein Aquarium, übergeben Sie einen String für die waterSupply und drucken Sie dann das Aquarium waterSupply.
fun genericsExample() {
    val aquarium2 = Aquarium("string")
    println(aquarium2.waterSupply)
}
  1. Führe dein Programm aus, um das Ergebnis zu beobachten.
⇒ string

Das Ergebnis ist der String, den Sie übergeben haben, da Aquarium keine Einschränkungen für T.Alle Typen, einschließlich String, festlegen kann.

  1. Erstellen Sie in genericsExample() einen weiteren Aquarium und übergeben Sie null für waterSupply. Wenn waterSupply null ist, drucken Sie "waterSupply is null".
fun genericsExample() {
    val aquarium3 = Aquarium(null)
    if (aquarium3.waterSupply == null) {
        println("waterSupply is null")
    }
}
  1. Führe dein Programm aus und beobachte das Ergebnis.
⇒ waterSupply is null

Warum kann null beim Erstellen von Aquarium weitergegeben werden? Das ist möglich, weil T standardmäßig für den Null-Typ Any? steht, der Typ oben in der Typhierarchie ist. Das Folgende entspricht Ihrer Eingabe.

class Aquarium<T: Any?>(val waterSupply: T)
  1. Wenn Sie die Übergabe von null nicht zulassen möchten, machen Sie T vom Typ Any, indem Sie ? nach Any entfernen.
class Aquarium<T: Any>(val waterSupply: T)

In diesem Zusammenhang wird Any als generische Einschränkung bezeichnet. Das bedeutet, dass jeder Typ für T weitergegeben werden kann, solange er null ist.

  1. Wenn du möchtest, kann nur WaterSupply (oder eine seiner Unterklassen) für T übergeben werden. Ersetze Any durch WaterSupply, um eine spezifischere allgemeine Einschränkung zu definieren.
class Aquarium<T: WaterSupply>(val waterSupply: T)

Schritt 4: Weitere Prüfungen hinzufügen

In diesem Schritt erfahren Sie mehr über die Funktion check(), mit der Sie sicherstellen können, dass Ihr Code wie erwartet funktioniert. Die Funktion check() ist eine Standardbibliotheksfunktion in Kotlin. Er dient als Assertion und löst eine IllegalStateException aus, wenn das Argument false ergibt.

  1. Füge eine addWater()Methode zur Klasse Aquarium hinzu, um Wasser hinzuzufügen, mit einer check(), die dafür sorgt, dass du das Wasser nicht erst verarbeiten musst.
class Aquarium<T: WaterSupply>(val waterSupply: T) {
    fun addWater() {
        check(!waterSupply.needsProcessing) { "water supply needs processing first" }
        println("adding water from $waterSupply")
    }    
}

In diesem Fall gibt check() eine Ausnahme aus, wenn needsProcessing „true“ ist.

  1. Füge in genericsExample() Code hinzu, um einen Aquarium mit LakeWater zu erstellen. Füge dann Wasser hinzu.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.addWater()
}
  1. Führe dein Programm durch und du erhältst eine Ausnahme, da das Wasser zuerst gefiltert werden muss.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first
        at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)
  1. Fügen Sie einen Aufruf hinzu, um das Wasser zu filtern, bevor Sie es Aquarium hinzufügen. Wenn du dein Programm ausführst, wird jetzt keine Ausnahme mehr geworfen.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.waterSupply.filter()
    aquarium4.addWater()
}
⇒ adding water from generics.LakeWater@880ec60

Die obige Anleitung behandelt die Grundlagen von generischen Aktionen. Die folgenden Aufgaben behandeln mehr, aber das wichtige Konzept ist die Deklaration und Verwendung einer generischen Klasse mit einer generischen Einschränkung.

In dieser Aufgabe erfahren Sie mehr über allgemeine und globale Typen. Der Typ in ist ein Typ, der nur in eine Klasse weitergegeben und nicht zurückgegeben werden kann. Der Typ out kann nur aus einer Klasse zurückgegeben werden.

Wenn Sie sich die Klasse Aquarium ansehen, stellen Sie fest, dass der allgemeine Typ nur beim Abrufen der Property waterSupply zurückgegeben wird. Es gibt keine Methoden, bei denen ein Wert vom Typ T als Parameter verwendet wird. Dies gilt nicht für seine Definition im Konstruktor. Mit Kotlin können Sie out-Typen für diesen Fall festlegen. Außerdem können Sie zusätzliche Informationen darüber gewinnen, wo die Typen sicher sind. Ebenso können Sie in-Typen für generische Typen definieren, die nur an Methoden übergeben und nicht zurückgegeben werden. So kann Kotlin zusätzliche Prüfungen auf Codesicherheit vornehmen.

Die Typen in und out sind Anweisungen für das Kotlin-Typsystem. In diesem Bootcamp wird das gesamte System erläutert, was ziemlich komplex ist. Der Compiler meldet außerdem Typen, die nicht als in und out gekennzeichnet sind, sodass Sie sie kennen sollten.

Schritt 1: Out-Typ definieren

  1. Ändern Sie in der Aquarium-Klasse T: WaterSupply in den Typ out.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    ...
}
  1. Geben Sie in derselben Datei außerhalb der Klasse eine Funktion addItemTo() an, die eine Aquarium von WaterSupply erwartet.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")
  1. Rufe addItemTo() bei genericsExample() an und führe dein Programm aus.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    addItemTo(aquarium)
}
⇒ item added

Kotlin kann dafür sorgen, dass addItemTo() nichts mit dem generischen WaterSupply tun kann, weil er als out-Typ deklariert ist.

  1. Wenn Sie das Keyword out entfernen, gibt der Compiler beim Aufrufen von addItemTo() einen Fehler aus. Dies liegt daran, dass der Kotlin-Code nicht sicher sein kann, dass er den Typ nicht einnimmt.

Schritt 2: Typ „in“ definieren

Der Typ in ähnelt dem Typ out, aber für allgemeine Typen, die nur an Funktionen übergeben werden, nicht zurückgegeben. Wenn Sie versuchen, einen in-Typ zurückzugeben, wird ein Compiler-Fehler angezeigt. In diesem Beispiel definierst du einen in-Typ als Teil einer Schnittstelle.

  1. Definieren Sie in Aquarium.kt eine Schnittstelle Cleaner, die einen generischen T verwendet, der auf WaterSupply beschränkt ist. Da es nur als Argument für clean() verwendet wird, können Sie es zu einem in-Parameter machen.
interface Cleaner<in T: WaterSupply> {
    fun clean(waterSupply: T)
}
  1. Wenn du die Schnittstelle Cleaner verwenden möchtest, erstelle eine Klasse TapWaterCleaner, die Cleaner zur Reinigung von TapWater implementiert, indem du Chemikalien hinzufügst.
class TapWaterCleaner : Cleaner<TapWater> {
    override fun clean(waterSupply: TapWater) =   waterSupply.addChemicalCleaners()
}
  1. Aktualisiere addWater() in der Aquarium-Klasse, um einen Cleaner vom Typ T zu erhalten und das Wasser vor dem Hinzufügen zu reinigen.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    fun addWater(cleaner: Cleaner<T>) {
        if (waterSupply.needsProcessing) {
            cleaner.clean(waterSupply)
        }
        println("water added")
    }
}
  1. Aktualisiere den genericsExample()-Beispielcode, um eine TapWaterCleaner (Aquarium) mit TapWater zu erstellen. Füge dann Wasser mit dem Reinigungsmittel hinzu. Der Reinigungsservice wird nach Bedarf verwendet.
fun genericsExample() {
    val cleaner = TapWaterCleaner()
    val aquarium = Aquarium(TapWater())
    aquarium.addWater(cleaner)
}

Kotlin verwendet die Informationen in und out, damit in deinem Code die generische Informationen sicher verwendet werden. Out und in können sich leicht merken: out-Typen können als Rückgabewerte übergeben werden, in-Typen als Argumente nach außen.

Wenn Sie sich mehr mit den Problemen der verschiedenen Typen und Typen befassen möchten, finden Sie in der Dokumentation ausführlichere Informationen dazu.

In dieser Aufgabe erfahren Sie mehr über allgemeine Funktionen und ihre Verwendung. Eine allgemeine Funktion ist in der Regel eine gute Idee, wenn die Funktion ein Argument einer Klasse mit einem allgemeinen Typ verwendet.

Schritt 1: Allgemeine Funktion erstellen

  1. Erstellen Sie in generics/Aquarium.kt die Funktion isWaterClean(), die Aquarium verwendet. Sie müssen den generischen Typ des Parameters angeben. Eine Option ist die Verwendung von WaterSupply.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
   println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}

Das bedeutet, dass Aquarium einen Parameter vom Typ out haben muss, damit dieser aufgerufen werden kann. Manchmal sind out oder in zu restriktiv, da Sie einen Typ für die Ein- und Ausgabe verwenden müssen. Sie können die Anforderung out entfernen, indem Sie die Funktion als generisch festlegen.

  1. Um die Funktion generisch zu machen, fügen Sie nach dem Keyword fun eckige Klammern mit dem generischen Typ T und eventuellen Einschränkungen, in diesem Fall WaterSupply, ein. Ändern Sie Aquarium, um durch T und nicht durch WaterSupply beschränkt zu werden.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
   println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}

T ist ein Typparameter für isWaterClean(), mit dem der generische Aquariumtyp angegeben wird. Diese Art von Verhalten ist gebräuchlich und es empfiehlt sich, sich einen Moment Zeit zu nehmen.

  1. Rufen Sie die Funktion isWaterClean() auf, indem Sie den Typ in spitzen Klammern direkt nach dem Funktionsnamen und vor den Klammern angeben.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean<TapWater>(aquarium)
}
  1. Aufgrund der Typinferenz aus dem Argument aquarium ist der Typ erforderlich. Entfernen Sie ihn daher. Führen Sie Ihr Programm aus und beobachten Sie die Ausgabe.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean(aquarium)
}
⇒ aquarium water is clean: false

Schritt 2: Allgemeine Methode mit korrigiertem Typ erstellen

Sie können auch für Klassen mit einem eigenen generischen Typ allgemeine Funktionen verwenden. In diesem Schritt fügen Sie eine allgemeine Methode zu Aquarium hinzu, um zu prüfen, ob sie den Typ WaterSupply hat.

  1. Deklarieren Sie in der Klasse Aquarium eine Methode, hasWaterSupplyOfType(), die einen generischen Parameter R verwendet (T wird bereits verwendet), der auf WaterSupply beschränkt ist, und true zurückgibt, wenn waterSupply den Typ R hat. Dies ist die Funktion, die Sie zuvor deklariert haben, aber innerhalb der Aquarium-Klasse.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
  1. Hinweis: Die letzte R ist rot unterstrichen. Bewegen Sie den Mauszeiger darauf, um den Fehler zu sehen.
  2. Für eine is-Prüfung müssen Sie Kotlin mitteilen, dass der Typ bearbeitet oder echt ist und in der Funktion verwendet werden kann. Setzen Sie hierzu inline vor das Keyword fun und reified vor den generischen Typ R.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R

Sobald ein Typ geändert wurde, können Sie ihn wie einen normalen Typ verwenden, da er nach der Inline-Anzeige ein echter Typ ist. Das bedeutet, dass du is-Prüfungen mit dem Typ durchführen kannst.

Wenn du reified hier nicht verwendest, wird der Typ nicht so real sein, dass Kotlin is-Prüfungen zulassen kann. Das liegt daran, dass nicht reparierte Typen nur beim Kompilieren verfügbar sind und von deinem Programm zur Laufzeit verwendet werden können. Diese Bedeutung wird im nächsten Abschnitt erläutert.

  1. Übergib TapWater als Typ. Wie beim Rufen von generischen Funktionen sollten Sie allgemeine Methoden mit spitzen Klammern des Typs nach dem Funktionsnamen aufrufen. Führe dein Programm aus und beobachte das Ergebnis.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())   // true
}
⇒ true

Schritt 3: Erweiterungsfunktionen erstellen

Sie können auch vereinheitlichte Typen für normale Funktionen und Erweiterungsfunktionen verwenden.

  1. Definieren Sie außerhalb der Aquarium-Klasse eine Erweiterungsfunktion unter WaterSupply mit dem Namen isOfType(), die prüft, ob die übergebene WaterSupply eines bestimmten Typs ist, z. B. TapWater.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T
  1. Rufen Sie die Erweiterungsfunktion genau wie bei einer Methode auf.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.waterSupply.isOfType<TapWater>())  
}
⇒ true

Bei diesen Erweiterungsfunktionen ist es Aquarium egal, um welche Aquarium es sich handelt oder ob es sich um eine TowerTank-Unterklasse handelt, solange es sich um eine Aquarium handelt. Die Syntax Sterne-Projektion ist eine bequeme Möglichkeit, eine Vielzahl von Übereinstimmungen anzugeben. Und wenn du eine Sternprojektion nutzt, sorgt Kotlin dafür, dass du nichts unsicher tust.

  1. Wenn du eine Sternprojektion verwenden möchtest, setze <*> nach Aquarium. Verschieben Sie hasWaterSupplyOfType() als Erweiterungsfunktion, da sie nicht Teil der Core API von Aquarium ist.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R
  1. Ändere den Anruf zu hasWaterSupplyOfType() und führe dein Programm aus.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())
}
⇒ true

In unserem Beispiel war es erforderlich, den generischen Typ als reified zu kennzeichnen und die Funktion inline festzulegen, weil Kotlin diese zur Laufzeit kennen muss, nicht nur die Kompilierungszeit.

Alle generischen Typen werden erst bei der Kompilierdauer von Kotlin verwendet. So kann vom Compiler für alles sicher gesorgt werden. Zur Laufzeit werden alle allgemeinen Typen gelöscht. Daher gilt die vorherige Fehlermeldung zum Prüfen eines gelöschten Typs.

Es stellte sich heraus, dass der Compiler korrekten Code erstellen kann, ohne die generischen Typen bis zur Laufzeit beizubehalten. Das bedeutet aber, dass mitunter, wie is, Prüfungen von allgemeinen Typen durch den Compiler nicht unterstützt. Deshalb wurden über Kotlin korrigierte oder echte Typen hinzugefügt.

Weitere Informationen zu reifizierten Typen und Typlöschungen finden Sie in der Kotlin-Dokumentation.

In dieser Lektion ging es um allgemeine Fragen, die wichtig für die Flexibilität und Wiederverwendung von Code sind.

  • Generische Klassen erstellen, um Code flexibler zu machen.
  • Fügen Sie generische Einschränkungen hinzu, um die mit generischen Elementen verwendeten Typen zu beschränken.
  • Verwenden Sie die Typen in und out mit generischen Typen, um eine bessere Typprüfung zu ermöglichen und die Einschränkung von Typen einzuschränken, die an Klassen übergeben oder von Klassen zurückgegeben werden.
  • Allgemeine Funktionen und Methoden für allgemeine Typen erstellen Beispiel:
    fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... }
  • Allgemeine Funktionen verwenden, um einer Klasse Funktionen hinzuzufügen, die keine Kernfunktionen sind
  • Aufgrund von Typlöschungen sind manchmal korrigierte Typen erforderlich. Im Gegensatz zu allgemeinen Typen bleiben die zusammengefassten Typen bis zur Laufzeit bestehen.
  • Prüfen Sie mit der check()-Funktion, ob der Code wie erwartet ausgeführt wird. Beispiel:
    check(!waterSupply.needsProcessing) { "water supply needs processing first" }

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.

Fragen beantworten

Frage 1

Welche der folgenden Regeln gelten für die Benennung eines generischen Typs?

<Gen>

<Generic>

<T>

<X>

Frage 2

Eine Einschränkung für die Typen, die für einen generischen Typ zulässig sind, wird genannt:

eine allgemeine Einschränkung

Eine allgemeine Einschränkung umfassen

Zuweisung des Kontingents

Ein allgemeines Limit für den Typ

Frage 3

„Verifiziert“ bedeutet:

▢ Der tatsächliche Effekt der Ausführung eines Objekts wurde berechnet.

▢ Für die Klasse wurde ein Eintrag für einen eingeschränkten Eintrag festgelegt.

▢ Der Parameter für den generischen Typ wurde in einen echten Typ umgewandelt.

▢ Es wurde eine Remote-Fehleranzeige ausgelöst.

Fahren Sie mit der nächsten Lektion fort: 6. Funktionelle Manipulation

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