Konstruktoren
Sie initialisieren ein neues Objekt, indem Sie Informationen an einen Konstruktor übergeben.
Jedes Objekt ist eine isolierte Welt. Ein Programm ist eine Sammlung von Objekten, daher löst die korrekte Initialisierung jedes einzelnen Objekts einen großen Teil des Initialisierungsproblems. Kotlin enthält Mechanismen, um eine ordnungsgemäße Initialisierung von Objekten zu gewährleisten.
Ein Konstruktor ist wie eine spezielle Mitgliedsfunktion, die ein neues Objekt initialisiert. Die einfachste Form eines Konstruktors ist eine einzeilige Klassendefinition:
// Constructors/Wombat.kt
class Wombat
fun main() {
val wombat = Wombat()
}
In main(), das Aufrufen von Wombat() erstellt ein Wombat-Objekt. Wenn Sie aus einer anderen objektorientierten Sprache kommen, könnten Sie erwarten, hier ein new-Schlüsselwort zu sehen, aber new wäre in Kotlin überflüssig, also wurde es weggelassen.
Sie übergeben Informationen an einen Konstruktor mit einer Parameterliste, genau wie bei einer Funktion. Hier nimmt der Alien-Konstruktor ein einziges Argument entgegen:
// Constructors/Arg.kt
class Alien(name: String) {
val greeting = "Poor $name!"
}
fun main() {
val alien = Alien("Mr. Meeseeks")
println(alien.greeting)
// alien.name // Error // [1]
}
/* Output:
Poor Mr. Meeseeks!
*/
Um ein Alien-Objekt zu erstellen, ist ein Argument erforderlich (versuchen Sie es ohne eines). name initialisiert die greeting-Eigenschaft innerhalb des Konstruktors, ist jedoch außerhalb des Konstruktors nicht zugänglich – versuchen Sie, die Zeile [1] zu entkommentieren.
Wenn Sie möchten, dass der Konstruktor-Parameter außerhalb des Klassenkörpers zugänglich ist, definieren Sie ihn als var oder val in der Parameterliste:
// Constructors/VisibleArgs.kt
class MutableNameAlien(var name: String)
class FixedNameAlien(val name: String)
fun main() {
val alien1 =
MutableNameAlien("Reverse Giraffe")
val alien2 =
FixedNameAlien("Krombopulos Michael")
alien1.name = "Parasite"
// Can't do this:
// alien2.name = "Parasite"
}
Diese Klassendefinitionen haben keine expliziten Klassenkörper—die Körper sind implizit.
Wenn name als var oder val definiert wird, wird es zu einer Eigenschaft und ist
somit außerhalb des Konstruktors zugänglich. val-Konstruktorparameter können nicht
geändert werden, während var-Konstruktorparameter veränderbar sind.
Ihre Klasse kann zahlreiche Konstruktorparameter haben:
// Constructors/MultipleArgs.kt
class AlienSpecies(
val name: String,
val eyes: Int,
val hands: Int,
val legs: Int
) {
fun describe() =
"$name with $eyes eyes, " +
"$hands hands and $legs legs"
}
fun main() {
val kevin =
AlienSpecies("Zigerion", 2, 2, 2)
val mortyJr =
AlienSpecies("Gazorpian", 2, 6, 2)
println(kevin.describe())
println(mortyJr.describe())
}
/* Output:
Zigerion with 2 eyes, 2 hands and 2 legs
Gazorpian with 2 eyes, 6 hands and 2 legs
*/
In Komplexe Konstruktoren, werden Sie sehen, dass Konstruktoren auch komplexe Initialisierungslogik enthalten können.
Wenn ein Objekt verwendet wird, wenn ein String erwartet wird, ruft Kotlin die toString()-Mitgliedsfunktion des Objekts auf. Wenn Sie keine schreiben, erhalten Sie trotzdem eine Standard-toString():
// Constructors/DisplayAlienSpecies.kt
fun main() {
val krombopulosMichael =
AlienSpecies("Gromflomite", 2, 2, 2)
println(krombopulosMichael)
}
/* Sample output:
AlienSpecies@4d7e1886
*/
Der Standard-toString() ist nicht sehr nützlich—er gibt den Klassennamen und die physikalische Adresse des Objekts aus (dies variiert von einer Programmausführung zur nächsten). Sie können Ihre eigene toString() definieren:
// Constructors/Scientist.kt
class Scientist(val name: String) {
override fun toString() =
"Scientist('$name')"
}
fun main() {
val zeep = Scientist("Zeep Xanflorp")
println(zeep)
}
/* Output:
Scientist('Zeep Xanflorp')
*/
override ist ein neues Schlüsselwort für uns. Es ist hier erforderlich, weil toString() bereits eine Definition hat, die eine primitive Ausgabe erzeugt. override teilt Kotlin mit, dass wir tatsächlich die Standarddefinition von toString() durch unsere eigene Definition ersetzen möchten. Die Deutlichkeit von override macht den Code klarer und verhindert Fehler.
Ein toString(), das den Inhalt eines Objekts in einer praktischen Form anzeigt, ist nützlich, um Programmierfehler zu finden und zu beheben. Um den Prozess des Debuggens zu vereinfachen, bieten IDEs Debugger an, die es Ihnen ermöglichen, jeden Schritt der Programmausführung zu beobachten und in Ihre Objekte hinein zu sehen.
Übungen und Lösungen finden Sie unter www.AtomicKotlin.com.