Dieses Codelab ist Teil des Kotlin-Bootcamps für Programmierer. Sie können diesen Kurs am besten nutzen, wenn Sie die Codelabs der Reihe nach durcharbeiten. Je nach Ihrem Wissen können Sie einige Abschnitte möglicherweise überfliegen. Dieser Kurs richtet sich an Programmierer, die eine objektorientierte Sprache kennen und Kotlin lernen möchten.
Einführung
In diesem Codelab lernen Sie generische Klassen, Funktionen und Methoden kennen und erfahren, wie sie in Kotlin funktionieren.
In diesem Kurs wird keine einzelne Beispiel-App entwickelt. Stattdessen sollen die Lektionen Ihr Wissen erweitern, sind aber weitgehend unabhängig voneinander, sodass Sie Abschnitte, mit denen Sie vertraut sind, überspringen können. Um die Beispiele zu veranschaulichen, wird in vielen ein Aquarium verwendet. Wenn Sie die ganze Geschichte des Aquariums sehen möchten, können Sie sich den Udacity-Kurs Kotlin Bootcamp for Programmers ansehen.
Was Sie bereits wissen sollten
- Die Syntax von Kotlin-Funktionen, -Klassen und -Methoden
- Neue Klasse in IntelliJ IDEA erstellen und Programm ausführen
Lerninhalte
- So arbeiten Sie mit generischen Klassen, Methoden und Funktionen
Aufgaben
- Allgemeine Klasse erstellen und Einschränkungen hinzufügen
in- undout-Typen erstellen- Generische Funktionen, Methoden und Erweiterungsfunktionen erstellen
Einführung in Generics
Wie viele Programmiersprachen hat auch Kotlin generische Typen. Mit einem generischen Typ können Sie eine Klasse generisch und damit viel flexibler machen.
Stellen Sie sich vor, Sie implementieren eine MyList-Klasse, die eine Liste von Elementen enthält. Ohne Generics müssten Sie für jeden Typ eine neue Version von MyList implementieren: eine für Double, eine für String und eine für Fish. Mit Generics können Sie die Liste generisch machen, sodass sie beliebige Objekttypen enthalten kann. Es ist, als würde man den Typ zu einem Platzhalter machen, der für viele Typen passt.
Um einen generischen Typ zu definieren, setzen Sie T in spitze Klammern <T> nach dem Klassennamen. Sie könnten auch einen anderen Buchstaben oder einen längeren Namen verwenden, aber die Konvention für einen generischen Typ ist „T“.
class MyList<T> {
fun get(pos: Int): T {
TODO("implement")
}
fun addItem(item: T) {}
}Sie können auf T verweisen, 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. Generische Listen sind natürlich sehr nützlich, daher ist die Klasse List in Kotlin integriert.
Schritt 1: Typografiehierarchie erstellen
In diesem Schritt erstellen Sie einige Klassen, die Sie im nächsten Schritt verwenden. Das Erstellen von Unterklassen wurde in einem früheren Codelab behandelt. Hier ist eine kurze Zusammenfassung.
- Damit das Beispiel übersichtlich bleibt, erstellen Sie ein neues Paket unter src und nennen Sie es
generics. - Erstellen Sie im Paket generics eine neue
Aquarium.kt-Datei. So können Sie Dinge mit denselben Namen ohne Konflikte neu definieren. Der restliche Code für dieses Codelab gehört also in diese Datei. - Erstelle eine Typenhierarchie für die verschiedenen Arten der Wasserversorgung. Machen Sie
WaterSupplyzuerst zu eineropen-Klasse, damit sie abgeleitet werden kann. - Fügen Sie einen booleschen
var-Parameter hinzu:needsProcessing. Dadurch wird automatisch eine veränderliche Property zusammen mit einer Getter- und einer Setter-Methode erstellt. - Erstelle eine Unterklasse
TapWater, dieWaterSupplyerweitert, und übergibtruefürneedsProcessing, da das Leitungswasser Zusatzstoffe enthält, die für Fische schädlich sind. - Definieren Sie in
TapWatereine Funktion namensaddChemicalCleaners(), dieneedsProcessingnach der Reinigung des Wassers auffalsesetzt. Das AttributneedsProcessingkann abTapWaterfestgelegt werden, da es standardmäßigpublicist und auf Unterklassen zugegriffen werden kann. Hier ist der vollständige Code.
package generics
open class WaterSupply(var needsProcessing: Boolean)
class TapWater : WaterSupply(true) {
fun addChemicalCleaners() {
needsProcessing = false
}
}- Erstellen Sie zwei weitere Unterklassen von
WaterSupplymit den NamenFishStoreWaterundLakeWater.FishStoreWatermuss nicht verarbeitet werden,LakeWatermuss aber mit der Methodefilter()gefiltert werden. Nach dem Filtern muss sie nicht noch einmal verarbeitet werden. Legen Sie daher infilter()needsProcessing = falsefest.
class FishStoreWater : WaterSupply(false)
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessing = false
}
}Weitere Informationen finden Sie in der vorherigen Lektion zur Vererbung in Kotlin.
Schritt 2: Generische Klasse erstellen
In diesem Schritt ändern Sie die Klasse Aquarium, um verschiedene Arten von Wasserversorgung zu unterstützen.
- Definieren Sie in Aquarium.kt eine
Aquarium-Klasse mit<T>in Klammern nach dem Klassennamen. - Fügen Sie
Aquariumdie unveränderliche EigenschaftwaterSupplyvom TypThinzu.
class Aquarium<T>(val waterSupply: T)- Schreibe eine Funktion mit dem Namen
genericsExample(). Da dies nicht Teil einer Klasse ist, kann es wie die Funktionmain()oder die Klassendefinitionen auf der obersten Ebene der Datei stehen. Erstellen Sie in der Funktion einAquariumund übergeben Sie einWaterSupply. Da der ParameterwaterSupplygenerisch ist, müssen Sie den Typ in spitzen Klammern<>angeben.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
}- In
genericsExample()kann Ihr Code auf diewaterSupplydes Aquariums zugreifen. Da es vom TypTapWaterist, können SieaddChemicalCleaners()ohne Typumwandlungen aufrufen.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}- Beim Erstellen des
Aquarium-Objekts können Sie die spitzen Klammern und den Inhalt dazwischen entfernen, da Kotlin eine Typinferenz hat. Es gibt also keinen Grund,TapWaterzweimal anzugeben, wenn Sie die Instanz erstellen. Der Typ kann aus dem Argument fürAquariumabgeleitet werden. Es wird trotzdem einAquariumvom TypTapWatererstellt.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}- Um zu sehen, was passiert, geben Sie
needsProcessingvor und nach dem Aufrufen vonaddChemicalCleaners()aus. Unten sehen Sie die vollständige 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}")
}- Fügen Sie eine
main()-Funktion hinzu, umgenericsExample()aufzurufen, führen Sie dann das Programm aus und sehen Sie sich das Ergebnis an.
fun main() {
genericsExample()
}⇒ water needs processing: true water needs processing: false
Schritt 3: Frage präzisieren
„Generisch“ bedeutet, dass Sie fast alles übergeben können, was manchmal ein Problem ist. In diesem Schritt legen Sie für die Klasse Aquarium genauer fest, was darin enthalten sein kann.
- Erstellen Sie in
genericsExample()einAquariumund übergeben Sie einen String fürwaterSupply. Geben Sie dann das AttributwaterSupplydes Aquariums aus.
fun genericsExample() {
val aquarium2 = Aquarium("string")
println(aquarium2.waterSupply)
}- Führen Sie das Programm aus und sehen Sie sich das Ergebnis an.
⇒ string
Das Ergebnis ist der übergebene String, da Aquarium keine Einschränkungen für T.festlegt. Es kann ein beliebiger Typ übergeben werden, einschließlich String.
- Erstellen Sie in
genericsExample()einen weiterenAquariumund übergeben Sienullfür denwaterSupply. WennwaterSupplynull ist, wird"waterSupply is null"ausgegeben.
fun genericsExample() {
val aquarium3 = Aquarium(null)
if (aquarium3.waterSupply == null) {
println("waterSupply is null")
}
}- Führen Sie das Programm aus und sehen Sie sich das Ergebnis an.
⇒ waterSupply is null
Warum kann ich null übergeben, wenn ich ein Aquarium erstelle? Das ist möglich, weil T standardmäßig für den Typ Any? steht, der Nullwerte zulässt und sich an der Spitze der Typhierarchie befindet. Das Folgende entspricht Ihrer vorherigen Eingabe.
class Aquarium<T: Any?>(val waterSupply: T)- Wenn Sie nicht zulassen möchten, dass
nullübergeben wird, müssen SieTexplizit vom TypAnymachen, indem Sie?nachAnyentfernen.
class Aquarium<T: Any>(val waterSupply: T)In diesem Zusammenhang wird Any als generische Einschränkung bezeichnet. Das bedeutet, dass für T jeder Typ übergeben werden kann, solange er nicht null ist.
- Sie möchten sicherstellen, dass für
Tnur einWaterSupply-Objekt (oder eines seiner untergeordneten Objekte) übergeben werden kann. Ersetzen SieAnydurchWaterSupply, um eine spezifischere generische Einschränkung zu definieren.
class Aquarium<T: WaterSupply>(val waterSupply: T)Schritt 4: Weitere Prüfungen hinzufügen
In diesem Schritt lernen Sie die Funktion check() kennen, mit der Sie dafür sorgen können, dass sich Ihr Code wie erwartet verhält. Die check()-Funktion ist eine Standardbibliotheksfunktion in Kotlin. Sie fungiert als Zusicherung und löst eine IllegalStateException aus, wenn ihr Argument als false ausgewertet wird.
- Fügen Sie der Klasse
AquariumeineaddWater()-Methode hinzu, um Wasser hinzuzufügen. Verwenden Sie dabei eincheck(), damit das Wasser nicht zuerst verarbeitet werden muss.
class Aquarium<T: WaterSupply>(val waterSupply: T) {
fun addWater() {
check(!waterSupply.needsProcessing) { "water supply needs processing first" }
println("adding water from $waterSupply")
}
}Wenn needsProcessing „true“ ist, löst check() eine Ausnahme aus.
- Füge in
genericsExample()Code hinzu, um einAquariummitLakeWaterzu erstellen, und füge dann etwas Wasser hinzu.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.addWater()
}- Wenn Sie das Programm ausführen, erhalten Sie 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)- Fügen Sie einen Aufruf zum Filtern des Wassers hinzu, bevor Sie es dem
Aquariumhinzufügen. Wenn Sie das Programm jetzt ausführen, wird keine Ausnahme ausgelöst.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.waterSupply.filter()
aquarium4.addWater()
}⇒ adding water from generics.LakeWater@880ec60
Das waren die Grundlagen zu Generics. Die folgenden Aufgaben decken mehr ab, aber das wichtige Konzept ist, wie eine generische Klasse mit einer generischen Einschränkung deklariert und verwendet wird.
In dieser Aufgabe lernen Sie In- und Out-Typen mit Generics kennen. Ein in-Typ ist ein Typ, der nur an eine Klasse übergeben, aber nicht zurückgegeben werden kann. Ein out-Typ ist ein Typ, der nur von einer Klasse zurückgegeben werden kann.
Wenn Sie sich die Klasse Aquarium ansehen, werden Sie feststellen, dass der generische Typ nur beim Abrufen des Attributs waterSupply zurückgegeben wird. Es gibt keine Methoden, die einen Wert vom Typ T als Parameter akzeptieren (außer bei der Definition im Konstruktor). In Kotlin können Sie out-Typen für genau diesen Fall definieren. Außerdem können zusätzliche Informationen darüber abgeleitet werden, wo die Typen sicher verwendet werden können. Ebenso können Sie in-Typen für generische Typen definieren, die nur an Methoden übergeben, aber nicht zurückgegeben werden. Dadurch kann Kotlin zusätzliche Prüfungen für die Codesicherheit durchführen.
Die Typen in und out sind Direktiven für das Typsystem von Kotlin. Das gesamte Typsystem zu erläutern, würde den Rahmen dieses Bootcamps sprengen. Der Compiler kennzeichnet jedoch Typen, die nicht entsprechend mit in und out gekennzeichnet sind.
Schritt 1: Out-Typ definieren
- Ändern Sie in der Klasse
Aquariumden Typ vonT: WaterSupplyinout.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
...
}- Deklarieren Sie in derselben Datei außerhalb der Klasse eine Funktion
addItemTo(), die eineAquariumvom TypWaterSupplyerwartet.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")- Rufen Sie
addItemTo()übergenericsExample()auf und führen Sie Ihr Programm aus.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
addItemTo(aquarium)
}⇒ item added
Kotlin kann dafür sorgen, dass addItemTo() keine typsicheren Aktionen mit dem generischen WaterSupply ausführt, da es als out-Typ deklariert ist.
- Wenn Sie das Keyword
outentfernen, gibt der Compiler beim Aufrufen vonaddItemTo()einen Fehler aus, da Kotlin nicht garantieren kann, dass Sie mit dem Typ nichts Unsicheres tun.
Schritt 2: „in“-Typ definieren
Der Typ in ähnelt dem Typ out, jedoch für generische Typen, die nur an Funktionen übergeben, aber nicht zurückgegeben werden. Wenn Sie versuchen, einen Typ in zurückzugeben, erhalten Sie einen Compilerfehler. In diesem Beispiel definieren Sie einen in-Typ als Teil einer Schnittstelle.
- Definieren Sie in Aquarium.kt eine Schnittstelle
Cleaner, die einen generischen TypTverwendet, der aufWaterSupplybeschränkt ist. Da er nur als Argument fürclean()verwendet wird, können Sie ihn zu einemin-Parameter machen.
interface Cleaner<in T: WaterSupply> {
fun clean(waterSupply: T)
}- Wenn Sie die
Cleaner-Schnittstelle verwenden möchten, erstellen Sie eine KlasseTapWaterCleaner, dieCleanerzum Reinigen vonTapWaterdurch Hinzufügen von Chemikalien implementiert.
class TapWaterCleaner : Cleaner<TapWater> {
override fun clean(waterSupply: TapWater) = waterSupply.addChemicalCleaners()
}- Aktualisieren Sie in der Klasse
AquariumaddWater(), um einCleanervom TypTzu verwenden, und reinigen Sie das Wasser, bevor Sie es hinzufügen.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
fun addWater(cleaner: Cleaner<T>) {
if (waterSupply.needsProcessing) {
cleaner.clean(waterSupply)
}
println("water added")
}
}- Aktualisieren Sie den Beispielcode für
genericsExample(), um einTapWaterCleanerund einAquariummitTapWaterzu erstellen. Fügen Sie dann mit dem Reiniger etwas Wasser hinzu. Der Reiniger wird nach Bedarf verwendet.
fun genericsExample() {
val cleaner = TapWaterCleaner()
val aquarium = Aquarium(TapWater())
aquarium.addWater(cleaner)
}Kotlin verwendet die Typinformationen in und out, um sicherzustellen, dass in Ihrem Code Generics sicher verwendet werden. Out und in sind leicht zu merken: out-Typen können als Rückgabewerte nach außen übergeben werden, in-Typen können als Argumente nach innen übergeben werden.

Wenn Sie mehr über die Art von Problemen erfahren möchten, die mit In- und Out-Typen gelöst werden, finden Sie in der Dokumentation ausführliche Informationen.
In dieser Aufgabe erfahren Sie mehr über generische Funktionen und wann Sie sie verwenden sollten. In der Regel ist es eine gute Idee, eine generische Funktion zu erstellen, wenn die Funktion ein Argument einer Klasse mit einem generischen Typ akzeptiert.
Schritt 1: Generische Funktion erstellen
- Erstellen Sie in generics/Aquarium.kt eine Funktion
isWaterClean(), die einAquariumakzeptiert. Sie müssen den generischen Typ des Parameters angeben. Eine Möglichkeit ist die Verwendung vonWaterSupply.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}Das bedeutet aber, dass Aquarium einen out-Typparameter haben muss, damit es aufgerufen werden kann. Manchmal sind out oder in zu restriktiv, da Sie einen Typ für Ein- und Ausgabe verwenden müssen. Sie können die Anforderung für out entfernen, indem Sie die Funktion generisch machen.
- Damit die Funktion generisch ist, setzen Sie nach dem Keyword
funspitze Klammern mit einem generischen TypTund allen Einschränkungen, in diesem FallWaterSupply. Ändern SieAquariumso, dass es durchTanstelle vonWaterSupplyeingeschränkt wird.
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 Typ des Aquariums angegeben wird. Dieses Muster ist sehr häufig und es ist eine gute Idee, sich einen Moment Zeit zu nehmen, um es durchzugehen.
- Rufen Sie die Funktion
isWaterClean()auf, indem Sie den Typ in spitzen Klammern direkt nach dem Funktionsnamen und vor den runden Klammern angeben.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean<TapWater>(aquarium)
}- Aufgrund der Typinferenz aus dem Argument
aquariumist der Typ nicht erforderlich. Entfernen Sie ihn. Führen Sie das Programm aus und beobachten Sie die Ausgabe.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean(aquarium)
}⇒ aquarium water is clean: false
Schritt 2: Generische Methode mit einem reifizierten Typ erstellen
Sie können auch generische Funktionen für Methoden verwenden, selbst in Klassen mit einem eigenen generischen Typ. In diesem Schritt fügen Sie Aquarium eine generische Methode hinzu, mit der geprüft wird, ob der Typ WaterSupply ist.
- Deklarieren Sie in der Klasse
Aquariumeine MethodehasWaterSupplyOfType(), die einen generischen ParameterR(Twird bereits verwendet) mit der EinschränkungWaterSupplyakzeptiert undtruezurückgibt, wennwaterSupplyvom TypRist. Das ist wie die Funktion, die Sie zuvor deklariert haben, nur innerhalb der KlasseAquarium.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R- Beachten Sie, dass das letzte
Rrot unterstrichen ist. Bewegen Sie den Mauszeiger darauf, um den Fehler zu sehen.
- Für eine
is-Prüfung müssen Sie Kotlin mitteilen, dass der Typ reified (real) ist und in der Funktion verwendet werden kann. Dazu setzen Sieinlinevor das Keywordfunundreifiedvor den generischen TypR.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is RSobald ein Typ reifiziert wurde, können Sie ihn wie einen normalen Typ verwenden, da er nach dem Inlining ein echter Typ ist. Das bedeutet, dass Sie mit dem Typ is-Prüfungen durchführen können.
Wenn Sie reified hier nicht verwenden, ist der Typ für Kotlin nicht „real“ genug, um is-Prüfungen zuzulassen. Das liegt daran, dass nicht reifizierte Typen nur zur Kompilierzeit verfügbar sind und nicht zur Laufzeit von Ihrem Programm verwendet werden können. Darauf wird im nächsten Abschnitt näher eingegangen.
- Übergeben Sie
TapWaterals Typ. Wie bei generischen Funktionen rufen Sie generische Methoden auf, indem Sie nach dem Funktionsnamen spitze Klammern mit dem Typ verwenden. Führen Sie das Programm aus und sehen Sie sich das Ergebnis an.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>()) // true
}⇒ true
Schritt 3: Erweiterungsfunktionen erstellen
Reifizierte Typen können auch für reguläre Funktionen und Erweiterungsfunktionen verwendet werden.
- Definieren Sie außerhalb der Klasse
Aquariumeine Erweiterungsfunktion fürWaterSupplynamensisOfType(), die prüft, ob das übergebeneWaterSupplyeinen bestimmten Typ hat, z. B.TapWater.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T- Rufen Sie die Erweiterungsfunktion wie eine Methode auf.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.waterSupply.isOfType<TapWater>())
}⇒ true
Bei diesen Erweiterungsfunktionen spielt es keine Rolle, welcher Typ von Aquarium verwendet wird (Aquarium, TowerTank oder eine andere Unterklasse), solange es sich um ein Aquarium handelt. Mit der Syntax für die Sternprojektion lassen sich auf einfache Weise verschiedene Übereinstimmungen angeben. Wenn Sie eine Sternprojektion verwenden, sorgt Kotlin dafür, dass Sie nichts Unsicheres tun.
- Wenn Sie eine Sternprojektion verwenden möchten, setzen Sie
<*>nachAquarium. VerschiebehasWaterSupplyOfType()in eine Erweiterungsfunktion, da sie nicht wirklich Teil der Core API vonAquariumist.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R- Ändern Sie den Aufruf in
hasWaterSupplyOfType()und führen Sie das Programm aus.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>())
}⇒ true
Im vorherigen Beispiel mussten Sie den generischen Typ als reified und die Funktion als inline markieren, da Kotlin sie zur Laufzeit und nicht nur zur Kompilierzeit kennen muss.
Alle generischen Typen werden von Kotlin nur zur Kompilierzeit verwendet. So kann der Compiler sicherstellen, dass Sie alles sicher ausführen. Zur Laufzeit werden alle generischen Typen gelöscht. Daher die frühere Fehlermeldung zum Prüfen eines gelöschten Typs.
Es stellt sich heraus, dass der Compiler korrekten Code erstellen kann, ohne die generischen Typen bis zur Laufzeit beizubehalten. Das bedeutet aber auch, dass Sie manchmal etwas tun, z. B. is-Prüfungen für generische Typen, das der Compiler nicht unterstützen kann. Deshalb wurden in Kotlin reifizierte oder reale Typen eingeführt.
Weitere Informationen zu reified types and type erasure finden Sie in der Kotlin-Dokumentation.
In dieser Lektion ging es um Generics, die wichtig sind, um Code flexibler und leichter wiederverwendbar zu machen.
- Generische Klassen erstellen, um Code flexibler zu gestalten
- Fügen Sie generische Einschränkungen hinzu, um die mit Generics verwendeten Typen zu begrenzen.
- Verwenden Sie die Typen
inundoutmit Generics, um eine bessere Typprüfung zu ermöglichen und die Typen einzuschränken, die an Klassen übergeben oder von Klassen zurückgegeben werden. - Generische Funktionen und Methoden für die Arbeit mit generischen Typen erstellen. Beispiel:
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... } - Verwenden Sie generische Erweiterungsfunktionen, um einer Klasse nicht zur Kernfunktionalität gehörende Funktionen hinzuzufügen.
- Reifizierte Typen sind manchmal aufgrund von Typauslöschung erforderlich. Reifizierte Typen bleiben im Gegensatz zu generischen Typen bis zur Laufzeit erhalten.
- Verwenden Sie die Funktion
check(), um zu prüfen, ob Ihr 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 weiterkommen, ist https://kotlinlang.org der beste Ausgangspunkt.
- Generics
- Allgemeine Einschränkungen
- Sternenprojektionen
In- undout-Typen- Reifizierte Parameter
- Type Erasure
check()-Funktion
Kotlin-Tutorials
Die Website https://try.kotlinlang.org enthält umfangreiche Tutorials namens „Kotlin Koans“, einen webbasierten Interpreter und eine vollständige Referenzdokumentation mit Beispielen.
Udacity-Kurs
Den Udacity-Kurs zu diesem Thema finden Sie unter Kotlin Bootcamp for Programmers.
IntelliJ IDEA
Dokumentation für IntelliJ IDEA finden Sie auf der JetBrains-Website.
In diesem Abschnitt werden mögliche Hausaufgaben für Schüler und Studenten aufgeführt, die dieses Codelab im Rahmen eines von einem Kursleiter geleiteten Kurses durcharbeiten. Es liegt in der Verantwortung des Kursleiters, Folgendes zu tun:
- Weisen Sie bei Bedarf Aufgaben zu.
- Teilen Sie den Schülern/Studenten mit, wie sie Hausaufgaben abgeben können.
- Benoten Sie die Hausaufgaben.
Lehrkräfte können diese Vorschläge nach Belieben nutzen und auch andere Hausaufgaben zuweisen, die sie für angemessen halten.
Wenn Sie dieses Codelab selbst durcharbeiten, können Sie mit diesen Hausaufgaben Ihr Wissen testen.
Beantworten Sie diese Fragen
Frage 1
Welche der folgenden Optionen ist die Konvention für die Benennung eines generischen Typs?
▢ <Gen>
▢ <Generic>
▢ <T>
▢ <X>
Frage 2
Eine Einschränkung der für einen generischen Typ zulässigen Typen wird als Folgendes bezeichnet:
▢ eine allgemeine Einschränkung
▢ eine generische Einschränkung
▢ Begriffsklärung
▢ ein generisches Typ-Limit
Frage 3
Reified bedeutet:
▢ Die tatsächlichen Auswirkungen der Ausführung eines Objekts wurden berechnet.
▢ Für die Klasse wurde ein eingeschränkter Index für Einträge festgelegt.
▢ Der generische Typparameter wurde in einen echten Typ umgewandelt.
▢ Eine Remote-Fehleranzeige wurde ausgelöst.
Fahren Sie mit der nächsten Lektion fort:
Eine Übersicht über den Kurs mit Links zu anderen Codelabs finden Sie unter „Kotlin Bootcamp for Programmers: Welcome to the course“.