
Hallo habrozhiteli! Das Buch von Josh Skin und David Greenhall basiert auf dem beliebten Kotlin Essentials-Kurs der Big Nerd Ranch. Anschauliche und nützliche Beispiele, klare Erklärungen zu Schlüsselkonzepten und grundlegenden APIs führen nicht nur die Kotlin-Sprache ein, sondern vermitteln auch den effektiven Einsatz ihrer Funktionen und ermöglichen Ihnen die Beherrschung der JetBrains IntelliJ IDEA-Entwicklungsumgebung.
Es spielt keine Rolle, ob Sie ein erfahrener Entwickler sind, der über Java hinausgehen möchte oder die erste Programmiersprache lernt. Josh und David werden Sie von den Grundprinzipien bis zur erweiterten Verwendung von Kotlin führen, damit Sie zuverlässige und effiziente Anwendungen erstellen können.
Für wen ist dieses Buch?
Wir (die Autoren) haben dieses Buch für Entwickler verschiedener Kaliber geschrieben: erfahrene Android-Entwickler, denen Java-Funktionen fehlen, Servercode-Entwickler, die an Kotlin-Funktionen interessiert sind, und auch für Anfänger, die sich entscheiden, eine effektive kompilierte Sprache zu lernen.
Dieses Buch könnte Sie für die Unterstützung von Android interessieren, ist jedoch nicht auf die Programmierung auf Kotlin für Android beschränkt. Darüber hinaus werden in diesem Buch nur in einem Kapitel - Kapitel 21 - Kotlin-Programmiertechniken für Android behandelt. Wenn Sie sich jedoch für das Thema der Verwendung von Kotlin für die Entwicklung von Android-Anwendungen interessieren, werden Sie in diesem Buch mit den grundlegenden Techniken vertraut gemacht, die das Schreiben von Android-Anwendungen in Kotlin vereinfachen.
Obwohl Kotlin von einigen anderen Sprachen beeinflusst wurde, müssen Sie nicht wissen, wie sie für eine erfolgreiche Zusammenarbeit mit Kotlin entwickelt wurden. Von Zeit zu Zeit werden wir Java- und Kotlin-Code vergleichen. Wenn Sie Erfahrung in der Entwicklung in Java haben, können Sie die Beziehung zwischen den beiden Sprachen besser verstehen. Und wenn Sie nicht über solche Erfahrungen verfügen, helfen Ihnen Beispiele zur Lösung derselben Probleme in einer anderen Sprache dabei, die Ideen zu verstehen, die die Bildung von Kotlin beeinflusst haben.
Wie man dieses Buch benutzt
Dieses Buch ist keine Referenz. Unser Ziel ist das konsequente Erlernen der Kotlin-Sprache. Sie arbeiten mit Projekten und lernen dabei die Sprache. Für eine bessere Wirkung empfehlen wir, dass Sie beim Lesen des Buches alle Codebeispiele ausprobieren. Wenn Sie mit Beispielen arbeiten, können Sie das Muskelgedächtnis entwickeln und Erkenntnisse gewinnen, mit denen Sie von einem Kapitel zum anderen wechseln können.
Jedes nächste Kapitel basiert auf dem vorherigen. Wir empfehlen, keine Kapitel zu überspringen. Auch wenn Sie das Thema während der Arbeit mit anderen Sprachen studiert haben, empfehlen wir Ihnen, zumindest hier darüber zu lesen: Viele Dinge werden in Kotlin anders implementiert. Wir beginnen mit einführenden Themen wie Variablen und Listen und gehen dann zu objektorientierten und funktionalen Programmiertechniken über, um zu verstehen, was Kotlin zu einem so leistungsstarken Werkzeug macht. Am Ende des Buches werden Sie von einem Anfänger zu einem fortgeschrittenen Entwickler auf Kotlin.
Wir möchten hinzufügen, dass Sie sich nicht beeilen sollten: Entwickeln Sie, verwenden Sie die Kotlin-Dokumentation unter dem Link:
kotlinlang.org/docs/reference , wo es Antworten auf viele Fragen gibt, die während der Experimente auftauchen.
Auszug. Erweiterungen
Mit Erweiterungen können Sie einem Typ Funktionen hinzufügen, ohne die Typdeklaration explizit zu ändern. Verwenden Sie Erweiterungen mit benutzerdefinierten Typen sowie mit Typen, auf die Sie keinen Einfluss haben, z. B. List, String und andere Typen aus der Kotlin-Standardbibliothek.
Erweiterungen sind eine Alternative zur Vererbung. Sie eignen sich gut zum Hinzufügen von Funktionen zu einem Typ, wenn Ihnen die Klassendefinition nicht zur Verfügung steht oder die Klasse keinen offenen Modifikator hat, mit dem Sie Unterklassen erstellen können.
Die Kotlin-Standardbibliothek verwendet häufig Erweiterungen. Beispielsweise sind die Standardfunktionen, die Sie in Kapitel 9 gelernt haben, deklarierte Erweiterungen. In diesem Kapitel finden Sie einige Beispiele für deren Deklaration.
In diesem Kapitel werden wir zuerst an einem Sandbox-Projekt arbeiten und dieses Wissen dann anwenden, um den NyetHack-Code zu optimieren. Öffnen Sie zunächst das Sandbox-Projekt und erstellen Sie eine neue Datei mit dem Namen Extensions.kt.
Erklärung der Erweiterungsfunktion
Mit Ihrer ersten Erweiterung können Sie String einen gewissen Grad an Begeisterung verleihen. Deklarieren Sie es in Extensions.kt.
Listing 18.1. Hinzufügen einer Erweiterung für den Typ String (Extensions.kt)
fun String.addEnthusiasm(amount: Int = 1) = this + "!".repeat(amount)
Erweiterungsfunktionen werden wie andere Funktionen deklariert, jedoch mit einem Unterschied: Wenn Sie eine Erweiterungsfunktion definieren, geben Sie auch einen Typ an, der als Empfangstyp bezeichnet wird und dem die Erweiterung Funktionen hinzufügt. (Erinnern Sie sich an Kapitel 9, in dem wir erweiterbare Typen als "Empfänger" bezeichnet haben.) Für die Funktion addEnthusiasm wird ein akzeptierender Zeichenfolgentyp angegeben.
Der Hauptteil der Funktion addEnthusiasm ist nur ein Ausdruck, der eine Zeichenfolge zurückgibt: Der Inhalt dieses und eines oder mehrerer Ausrufezeichen, abhängig vom Wert des Betragsarguments (1 ist der Standardwert). Das Schlüsselwort this bezieht sich auf die Instanz des Zielobjekts, für das die Erweiterung aufgerufen wird (in diesem Fall die String-Instanz).
Jetzt können Sie die Funktion addEnthusiasm für jede Instanz von String aufrufen. Versuchen Sie eine neue Erweiterungsfunktion, indem Sie eine Zeile in der Hauptfunktion deklarieren und die Erweiterungsfunktion addEnthusiasm aufrufen, damit das Ergebnis ausgegeben wird.
Listing 18.2. Aufrufen einer neuen Erweiterung für eine Instanz des String-Empfängerobjekts (Extensions.kt)
fun String.addEnthusiasm(amount: Int = 1) = this + "!".repeat(amount) fun main(args: Array<String>) { println("Madrigal has left the building".addEnthusiasm()) }
Führen Sie Extensions.kt aus und prüfen Sie, ob die Erweiterungsfunktion der Zeichenfolge wie vorgesehen ein Ausrufezeichen hinzufügt.
Ist es möglich, String in eine Unterklasse zu unterteilen, um diese Funktion zu String-Instanzen hinzuzufügen? Überprüfen Sie in IntelliJ den Quellcode für die String-Deklaration, indem Sie zweimal die Umschalttaste drücken, um das Dialogfeld "Überall suchen" zu öffnen, und geben Sie "String.kt" in das Suchfeld ein. Sie sehen diese Klassendeklaration:
public class String : Comparable<String>, CharSequence { ... }
Da das Schlüsselwort open nicht in der Deklaration der String-Klasse enthalten ist, können Sie String nicht in Unterklassen unterteilen, um durch Vererbung neue Features hinzuzufügen. Wie bereits erwähnt, sind Erweiterungen eine gute Option, wenn Sie einer Klasse Funktionen hinzufügen möchten, die Sie nicht verwalten oder nicht zum Erstellen einer Unterklasse verwenden können.
Erklärung zur Erweiterung der Oberklasse
Erweiterungen basieren nicht auf Vererbung, können jedoch mit Vererbung kombiniert werden, um den Umfang zu erhöhen. Versuchen Sie dies in Extensions.kt: Deklarieren Sie eine Erweiterung für den Typ Any mit dem Namen easyPrint. Da die Erweiterung für Beliebig deklariert ist, ist sie für alle Typen verfügbar. Ersetzen Sie im Wesentlichen den Funktionsaufruf println durch den Aufruf der Erweiterung easyPrint für String.
Listing 18.3. Beliebige Erweiterung (Extensions.kt)
fun String.addEnthusiasm(amount: Int = 1) = this + "!".repeat(amount) fun Any.easyPrint() = println(this) fun main(args: Array<String>) { println("Madrigal has left the building".addEnthusiasm()).easyPrint() }
Führen Sie Extensions.kt aus und stellen Sie sicher, dass sich die Ausgabe nicht geändert hat.
Da Sie die Erweiterung für den Typ Beliebig hinzugefügt haben, ist sie auch für Untertypen verfügbar. Fügen Sie einen Nebenstellenaufruf für Int.
Listing 18.4. easyPrint ist für alle Untertypen verfügbar (Extensions.kt)
fun String.addEnthusiasm(amount: Int = 1) = this + "!".repeat(amount) fun Any.easyPrint() = println(this) fun main(args: Array<String>) { "Madrigal has left the building".addEnthusiasm().easyPrint() 42.easyPrint() }
Allgemeine Erweiterungsfunktionen
Aber was ist, wenn Sie die Zeile „Madrigal hat das Gebäude verlassen“ vor und nach addEnthusiasm drucken möchten?
Fügen Sie dazu der easyPrint-Funktion die Möglichkeit hinzu, die Kette aufzurufen. Sie haben bereits Ketten von Funktionsaufrufen gesehen: Funktionen können an einer Kette teilnehmen, wenn sie ein Empfängerobjekt oder ein anderes Objekt zurückgeben, für das nachfolgende Funktionen aufgerufen werden können.
Aktualisieren Sie easyPrint, um die Verkettung aufzurufen.
Listing 18.5. Ändern Sie easyPrint, um die Verkettung aufzurufen (Extensions.kt).
fun String.addEnthusiasm(amount: Int = 1) = this + "!".repeat(amount) fun Any.easyPrint()= println(this): Any { println(this) return this } ...
Versuchen Sie nun zweimal, die easyPrint-Funktion aufzurufen: vor und nach addEnthusiasm.
Listing 18.6. Rufen Sie easyPrint zweimal auf (Extensions.kt)
fun String.addEnthusiasm(amount: Int = 1) = this + "!".repeat(amount) fun Any.easyPrint(): Any { println(this) return this } fun main(args: Array<String>) { "Madrigal has left the building".easyPrint().addEnthusiasm().easyPrint() 42.easyPrint() }
Der Code wurde nicht kompiliert. Der erste easyPrint-Aufruf war zulässig, addEnthusiasm jedoch nicht. Sehen Sie sich die Typinformationen an, um zu verstehen, warum dies geschieht: Klicken Sie auf easyPrint und drücken Sie Strg-Umschalt-P (Strg-P). Wählen Sie aus der Liste der angezeigten Erweiterungen die erste aus: ("Madrigal hat das Gebäude verlassen .easyPrint ()") (Abb. 18.1).
Die easyPrint-Funktion gibt die Zeichenfolge zurück, für die sie aufgerufen wurde, verwendet jedoch den Any-Typ, um sie darzustellen. addEnthusiasm ist nur für String verfügbar, daher kann es nicht für den von easyPrint zurückgegebenen Wert aufgerufen werden.
Um dieses Problem zu lösen, können Sie eine allgemeine Erweiterung vornehmen. Aktualisieren Sie die easyPrint-Erweiterungsfunktion und verwenden Sie den generischen Typ als Akzeptor anstelle von Any.
Listing 18.7. Generalisierung von easyPrint (Extensions.kt)
fun String.addEnthusiasm(amount: Int = 1) = this + "!".repeat(amount) fun <T> AnyT.easyPrint(): AnyT { println(this) return this } ...
Wenn die Erweiterung nun den Parameter des verallgemeinerten Typs T als Empfänger verwendet und T anstelle von Beliebig zurückgibt, werden Informationen über den spezifischen Typ des Empfängerobjekts über die Kette weitergegeben (Abb. 18.2).
Versuchen Sie erneut, Extensions.kt auszuführen. Diesmal wird die Zeile zweimal ausgegeben:
Madrigal has left the building Madrigal has left the building! 42
Ihre neue verallgemeinerte Erweiterungsfunktion funktioniert mit jedem Typ und verarbeitet auch Informationen darüber. Mit Erweiterungen, die generische Typen verwenden, können Sie Funktionen schreiben, die mit einer Vielzahl von Typen in einem Programm arbeiten können.
Erweiterungen für generische Typen sind auch in der Kotlin-Standardbibliothek verfügbar. Schauen Sie sich zum Beispiel die Deklaration der let-Funktion an:
public inline fun <T, R> T.let(block: (T) -> R): R { return block(this) }
let wird als generische Erweiterungsfunktion deklariert, die es ermöglicht, mit allen Typen zu arbeiten. Es wird ein Lambda verwendet, das das Empfängerobjekt als Argument (T) verwendet und den Wert eines neuen Typs R zurückgibt.
Beachten Sie das Inline-Schlüsselwort, das wir in Kapitel 5 kennengelernt haben. Der gleiche Rat, den wir zuvor gegeben haben, gilt auch hier: Wenn Sie eine Erweiterungsfunktion als integriert deklarieren, wenn sie ein Lambda akzeptiert, werden die Speicherkosten reduziert.
»Weitere Informationen zum Buch finden Sie auf
der Website des Herausgebers»
Inhalt»
Auszug25% Rabatt auf Gutschein für Khabrozhitel -
KotlinNach Bezahlung der Papierversion des Buches wird ein elektronisches Buch per E-Mail verschickt.