Kotlin ist eine Programmiersprache. die weltweit von Android-Entwicklern weit verbreitet sind. Dieses Thema dient als Kotlin-Code Crashkurs für einen schnellen Einstieg.
Variablendeklaration
In Kotlin werden zum Deklarieren von Variablen zwei verschiedene Keywords verwendet: val
und var
.
- Verwenden Sie
val
für eine Variable, deren Wert sich nie ändert. Sie können keinen Wert neu zuweisen in eine Variable übergeben, die mitval
deklariert wurde. - Verwenden Sie
var
für eine Variable, deren Wert sich ändern kann.
Im folgenden Beispiel ist count
eine Variable vom Typ Int
, der ein
Anfangswert von 10
:
var count: Int = 10
Int
ist ein Typ, der eine Ganzzahl darstellt, einer von vielen numerischen Typen,
in Kotlin dargestellt werden können. Ähnlich wie bei anderen Sprachen können Sie auch
Byte
, Short
, Long
, Float
und Double
abhängig von Ihren numerischen Daten.
Das Keyword var
bedeutet, dass Sie count
Werte nach Bedarf neu zuweisen können. Für
Sie können beispielsweise den Wert von count
von 10
in 15
ändern:
var count: Int = 10
count = 15
Einige Werte sollen jedoch nicht geändert werden. Beispiel: String
mit dem Namen
languageName
. Wenn languageName
immer einen Wert enthalten soll
"Kotlin" enthält, können Sie languageName
mit dem Schlüsselwort val
deklarieren:
val languageName: String = "Kotlin"
Mit diesen Keywords können Sie genau angeben, was geändert werden kann. Sie können sie für Folgendes nutzen:
Ihren Vorteil je nach Bedarf. Wenn ein Variablenverweis neu zuweisbar sein muss,
deklarieren Sie es als var
. Andernfalls verwenden Sie val
.
Typinferenz
In Anlehnung an das vorherige Beispiel werden Sie beim Zuweisen eines Anfangswerts
languageName
, kann der Kotlin-Compiler den Typ basierend auf dem Typ
den zugewiesenen Wert.
Da der Wert von "Kotlin"
vom Typ String
ist, leitet der Compiler Folgendes ab:
languageName
ist auch ein String
. Kotlin ist ein statisch typisierter
Sprache. Das bedeutet, dass der Typ zum Kompilierungszeitpunkt aufgelöst wird und nie
Änderungen.
Im folgenden Beispiel wird languageName
als String
abgeleitet. Sie können also
alle Funktionen aufrufen, die nicht zur Klasse String
gehören:
val languageName = "Kotlin"
val upperCaseName = languageName.toUpperCase()
// Fails to compile
languageName.inc()
toUpperCase()
ist eine Funktion, die nur für Variablen des Typs
String
. Da der Kotlin-Compiler languageName
als String
abgeleitet hat,
können Sie sicher toUpperCase()
anrufen. inc()
ist jedoch ein Int
-Operator
daher kann sie nicht für String
aufgerufen werden. Der Typ von Kotlin-Typ
Ableitung ermöglicht Ihnen Präzision und Typsicherheit.
Nullsicherheit
In einigen Sprachen kann eine Referenztypvariable deklariert werden, ohne einen expliziten Anfangswert. In diesen Fällen enthalten die Variablen normalerweise einen NULL-Wert Wert. Kotlin-Variablen dürfen standardmäßig keine Nullwerte enthalten. Das bedeutet, dass der folgendes Snippet ist ungültig:
// Fails to compile
val languageName: String = null
Damit eine Variable einen Nullwert enthalten kann, muss sie vom Typ Nullwerte zulässig sein. Sie können
Sie können eine Variable als Nullwerte angeben, indem Sie ihrem Typ als Suffix ?
hinzufügen, wie hier gezeigt
im folgenden Beispiel:
val languageName: String? = null
Bei einem String?
-Typ können Sie entweder einen String
-Wert oder einen null
-Wert
languageName
.
Sie müssen mit Variablen, für die Nullwerte zulässig sind, vorsichtig umgehen, da sonst ein gefürchtetes Risiko besteht.
NullPointerException
Wenn Sie in Java beispielsweise versuchen, eine Methode
bei einem Nullwert ab, stürzt das Programm ab.
Kotlin bietet eine Reihe von Mechanismen für die sichere Arbeit mit Nullwerten Variablen. Weitere Informationen finden Sie unter Gängige Kotlin-Muster in Android: Null-Zulässigkeit
Bedingungen
Kotlin bietet mehrere Mechanismen zum Implementieren bedingter Logik. Die meisten
Dazu gehört häufig eine if-else-Anweisung. Wenn ein Ausdruck in
Klammern neben einem if
-Keyword wird als true
ausgewertet, dann wird der Code in
diesem Zweig (d.h. der direkt nachfolgende Code, der in geschweifte Klammern gesetzt ist)
geschweifte Klammern) wird ausgeführt. Andernfalls wird der Code im Zweig else
ausgeführt.
if (count == 42) {
println("I have the answer.")
} else {
println("The answer eludes me.")
}
Sie können mehrere Bedingungen mit else if
darstellen. Auf diese Weise können Sie
eine detailliertere, komplexe Logik innerhalb einer einzelnen bedingten Anweisung, wie in
im folgenden Beispiel:
if (count == 42) {
println("I have the answer.")
} else if (count > 35) {
println("The answer is close.")
} else {
println("The answer eludes me.")
}
Bedingte Anweisungen sind nützlich, um zustandsorientierte Logik darzustellen. Sie können
dass Sie sich beim Schreiben wiederholen. Im obigen Beispiel
geben Sie einfach in jedem Zweig ein String
aus. Um diese Wiederholung zu vermeiden, bietet Kotlin
bedingten Ausdrücken. Das letzte Beispiel kann so umgeschrieben werden:
val answerString: String = if (count == 42) {
"I have the answer."
} else if (count > 35) {
"The answer is close."
} else {
"The answer eludes me."
}
println(answerString)
Implizit gibt jeder bedingte Zweig das Ergebnis des Ausdrucks auf seiner
in der letzten Zeile, sodass Sie kein return
-Keyword verwenden müssen. Da das Ergebnis
alle drei Zweige vom Typ String
sind, lautet das Ergebnis des if-else-Ausdrucks:
ebenfalls vom Typ String
. In diesem Beispiel ist answerString
ein Anfangsbuchstabe zugewiesen
Wert aus dem Ergebnis des if-else-Ausdrucks. Typinferenz kann verwendet werden, um
die explizite Typdeklaration für answerString
wegzulassen, aber das ist oft
um sie zur Verdeutlichung aufzunehmen.
Wenn die Komplexität Ihrer bedingten Anweisung zunimmt, sollten Sie Ersetzen Sie Ihren if-else-Ausdruck durch einen when-Ausdruck, wie in den folgendes Beispiel:
val answerString = when {
count == 42 -> "I have the answer."
count > 35 -> "The answer is close."
else -> "The answer eludes me."
}
println(answerString)
Jeder Zweig in einem when
-Ausdruck wird durch eine Bedingung, einen Pfeil
(->
) und ein Ergebnis. Wenn die Bedingung auf der linken Seite des Pfeils
als wahr ausgewertet, dann ist das Ergebnis des Ausdrucks auf der rechten Seite
zurückgegeben. Beachten Sie, dass die Ausführung nicht von einem Zweig zum nächsten erfolgt.
Der Code im Beispiel für den when
-Ausdruck entspricht funktional dem Code in
aus dem vorherigen Beispiel, ist aber wohl leichter zu lesen.
Die Bedingungen von Kotlin heben eines der leistungsstärkeren Funktionen hervor, intelligentes Streamen. Anstatt den Operator „safe-call“ oder den Operator „not-null“ zu verwenden um mit Werten zu arbeiten, für die Nullwerte zulässig sind, können Sie stattdessen prüfen, Variable enthält einen Verweis auf einen Nullwert mithilfe einer bedingten Anweisung, wie Beispiel:
val languageName: String? = null
if (languageName != null) {
// No need to write languageName?.toUpperCase()
println(languageName.toUpperCase())
}
Innerhalb des bedingten Zweigs kann languageName
so behandelt werden, als ob keine Nullwerte zulässig sind.
Kotlin ist so intelligent, dass sie erkennt, dass die Bedingung für die Ausführung des Branch
ist, dass languageName
keinen Nullwert enthält. Sie müssen also
languageName
in diesem Zweig als Nullwerte zulässig. Diese intelligente Übertragung funktioniert für null
Überprüfungen,
Typprüfungen,
oder eine Bedingung erfüllen, die ein
Vertrag.
Funktionen
Sie können einen oder mehrere Ausdrücke in einer Funktion gruppieren. Anstatt die App zu wiederholen jedes Mal, wenn Sie ein Ergebnis benötigen, die gleiche Reihe von Ausdrücken enthält, die Ausdrücke in einer Funktion ansehen und stattdessen diese Funktion aufrufen.
Um eine Funktion zu deklarieren, verwenden Sie das Schlüsselwort fun
, gefolgt vom Funktionsnamen.
Definieren Sie als Nächstes die Eingabetypen,
falls zutreffend, und deklarieren Sie
die Art der zurückgegebenen Ausgabe. Im Text einer Funktion definieren Sie
Ausdrücke, die beim Aufrufen Ihrer Funktion aufgerufen werden.
Aufbauend auf den vorherigen Beispielen finden Sie hier eine vollständige Kotlin-Funktion:
fun generateAnswerString(): String {
val answerString = if (count == 42) {
"I have the answer."
} else {
"The answer eludes me"
}
return answerString
}
Die Funktion im obigen Beispiel hat den Namen generateAnswerString
. Es
nimmt keine Eingaben vor. Es wird ein Ergebnis vom Typ String
ausgegeben. So rufen Sie eine
-Funktion ihren Namen, gefolgt vom Aufrufoperator (()
) ein. Im
Im Beispiel unten wird die Variable answerString
mit dem Ergebnis aus
generateAnswerString()
val answerString = generateAnswerString()
Funktionen können Argumente als Eingabe annehmen, wie im folgenden Beispiel gezeigt:
fun generateAnswerString(countThreshold: Int): String {
val answerString = if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
return answerString
}
Beim Deklarieren einer Funktion können Sie eine beliebige Anzahl von Argumenten und deren
Typen. Im obigen Beispiel verwendet generateAnswerString()
ein Argument mit dem Namen
countThreshold
vom Typ Int
. Innerhalb der Funktion können Sie auf das
Argument mithilfe seines Namens.
Wenn Sie diese Funktion aufrufen, müssen Sie in der Funktion ein Argument angeben. in Klammern:
val answerString = generateAnswerString(42)
Vereinfachung von Funktionsdeklarationen
generateAnswerString()
ist eine ziemlich einfache Funktion. Mit der Funktion wird ein
und kehrt sofort zurück. Wenn das Ergebnis eines einzelnen Ausdrucks
zurückgegeben wird, können Sie die Deklaration einer lokalen Variable überspringen,
gibt das Ergebnis des in der Funktion enthaltenen if-else-Ausdrucks zurück:
Beispiel:
fun generateAnswerString(countThreshold: Int): String {
return if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
}
Sie können das Rückgabe-Keyword auch durch den Zuweisungsoperator ersetzen:
fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
"I have the answer"
} else {
"The answer eludes me"
}
Anonyme Funktionen
Nicht jede Funktion benötigt einen Namen. Einige Funktionen lassen sich ihre Ein- und Ausgaben. Diese Funktionen werden als anonyme Funktionen bezeichnet. Ich einen Verweis auf eine anonyme Funktion beibehalten, indem dieser Verweis auf später die anonyme Funktion aufrufen. Du kannst die Referenz auch wie bei anderen Referenztypen.
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
Wie benannte Funktionen können auch anonyme Funktionen eine beliebige Anzahl von Ausdrücken enthalten. Der von der Funktion zurückgegebene Wert ist das Ergebnis des endgültigen Ausdrucks.
Im obigen Beispiel enthält stringLengthFunc
einen Verweis auf eine anonyme
-Funktion, die eine String
als Eingabe verwendet und die Länge der Eingabe zurückgibt
String
als Ausgabe vom Typ Int
. Daher lautet der Typ der Funktion
gekennzeichnet als (String) -> Int
. Dieser Code ruft die Funktion jedoch nicht auf.
Um das Ergebnis der Funktion abzurufen, müssen Sie sie wie mit einem
benannte Funktion ein. Sie müssen beim Aufrufen von stringLengthFunc
eine String
angeben, wie
Beispiel:
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
val stringLength: Int = stringLengthFunc("Android")
Höhere Funktionen
Eine Funktion kann eine andere Funktion als Argument annehmen. Funktionen, die andere Funktionen als Argumente werden als Funktionen höherer Ordnung bezeichnet. Dieses Muster ist nützlich für die Kommunikation zwischen Komponenten, so wie Sie es auch mit einem Callback-Schnittstelle in Java verwenden.
Hier ist ein Beispiel für eine übergeordnete Funktion:
fun stringMapper(str: String, mapper: (String) -> Int): Int {
// Invoke function
return mapper(str)
}
Die stringMapper()
-Funktion übernimmt eine String
zusammen mit einer Funktion, die
leitet einen Int
-Wert aus einer String
ab, die Sie ihm übergeben.
Sie können stringMapper()
aufrufen, indem Sie ein String
und eine Funktion übergeben,
den anderen Eingabeparameter erfüllt, nämlich eine Funktion, die ein String
als
ein Int
ein- und ausgibt, wie im folgenden Beispiel gezeigt:
stringMapper("Android", { input ->
input.length
})
Wenn die anonyme Funktion der letzte Parameter ist, der für eine Funktion definiert ist, können Sie außerhalb der zum Aufrufen der Funktion verwendeten Klammern übergeben, wie in der folgendes Beispiel:
stringMapper("Android") { input ->
input.length
}
Anonyme Funktionen sind in der gesamten Kotlin-Standardbibliothek zu finden. Für finden Sie unter Funktionen höherer Ordnung und Lambdas:
Klassen
Alle bisher erwähnten Typen sind in die Kotlin-Programmierung integriert.
Sprache. Wenn Sie einen eigenen benutzerdefinierten Typ hinzufügen möchten, können Sie eine Klasse definieren
mit dem Schlüsselwort class
, wie im folgenden Beispiel gezeigt:
class Car
Properties
Klassen stellen den Zustand mithilfe von Eigenschaften dar. A
property ist
Eine Variable auf Klassenebene, die einen Getter, einen Setter und ein unterstützendes Feld enthalten kann.
Da ein Auto zum Anfahren Räder benötigt, können Sie eine Liste mit Wheel
-Objekten als
von Car
, wie im folgenden Beispiel gezeigt:
class Car {
val wheels = listOf<Wheel>()
}
wheels
ist eine public val
, d. h., wheels
kann über
außerhalb des Car
-Kurses und kann nicht neu zugewiesen werden. Wenn Sie eine
Instanz von Car
müssen Sie zuerst dessen Konstruktor aufrufen. Hier können Sie
auf ihre barrierefreien Properties zuzugreifen.
val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car
Wenn Sie Ihre Räder anpassen möchten, können Sie einen benutzerdefinierten Konstruktor definieren, der gibt an, wie Ihre Klassenattribute initialisiert werden:
class Car(val wheels: List<Wheel>)
Im obigen Beispiel übernimmt der Klassenkonstruktor ein List<Wheel>
als
-Konstruktor und verwendet dieses Argument, um sein wheels
-Element zu initialisieren
Property.
Klassenfunktionen und Kapselung
Klassen verwenden Funktionen, um das Verhalten zu modellieren. Funktionen können den Status ändern um nur die Daten sichtbar zu machen, die Sie bereitstellen möchten. Diese Zugriffssteuerung gehört zu ein größeres objektorientiertes Konzept, die Datenkapselung.
Im folgenden Beispiel wird das Attribut doorLock
vor allem privat behandelt.
außerhalb der Car
-Klasse. Wenn du das Auto entriegeln möchtest, musst du die unlockDoor()
aufrufen
-Funktion übergeben einen gültigen Schlüssel, wie im folgenden Beispiel gezeigt:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
Wenn Sie anpassen möchten, wie auf eine Property verwiesen wird, können Sie eine
einen benutzerdefinierten Getter und Setter. Wenn Sie beispielsweise das Attribut
und den Zugriff auf seinen Setter einschränken, können Sie diesen Setter als
private
:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
var gallonsOfFuelInTank: Int = 15
private set
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
Mit einer Kombination aus Eigenschaften und Funktionen können Sie Klassen erstellen, alle Objekttypen modellieren.
Interoperabilität
Eine der wichtigsten Funktionen von Kotlin ist die fließende Interoperabilität mit Java. Da Kotlin-Code in JVM-Bytecode kompiliert wird, kann Ihr Kotlin-Code direkt in Java-Code ein und umgekehrt. Das bedeutet, dass Sie vorhandene Java-Bibliotheken direkt von Kotlin abrufen. Darüber hinaus hat die Mehrheit der Android APIs sind in Java geschrieben und können direkt aus Kotlin aufgerufen werden.
Nächste Schritte
Kotlin ist eine flexible, pragmatische Sprache mit zunehmender Unterstützung und Dynamik. Mi. Probieren Sie es einfach aus, falls Sie dies noch nicht getan haben. Die nächsten Schritte findest du in der offiziellen Kotlin-Dokumentation sowie den Leitfaden zur Häufige Kotlin-Muster in Ihren Android-Apps