Kotlin ist eine moderne Programmiersprache, die Java-Bytecode kompiliert. Es ist kostenlos und Open Source und verspricht, die Kodierung für Android noch mehr Spaß zu machen.
Im vorherigen Artikel haben Sie erfahren, wie Sie Funktionen wie Erweiterungsfunktionen, Schließungen, Funktionen höherer Ordnung und Inline-Funktionen in Kotlin verwenden können.
In diesem Beitrag erhalten Sie eine Einführung in die objektorientierte Programmierung in Kotlin, indem Sie etwas über Klassen lernen: Konstruktoren und Eigenschaften, Casting und erweiterte Klassenfunktionen, die Kotlin einfach macht.
Eine Klasse ist eine Programmeinheit, in der Funktionen und Daten zur Ausführung verwandter Aufgaben zusammengefasst werden. Wir erklären eine Klasse in Kotlin mit der Klasse
Schlüsselwort ähnlich Java.
Klassenbuch
Der vorhergehende Code ist die einfachste Klassendeklaration. Wir haben soeben eine leere Klasse erstellt Buch
. Wir können diese Klasse auch dann instanziieren, wenn sie keinen Körper enthält, der ihren Standardkonstruktor verwendet.
val book = Buch ()
Wie Sie im obigen Code sehen können, haben wir das nicht verwendet Neu
Schlüsselwort zum Instanziieren dieser Klasse, wie es in anderen Programmiersprachen üblich ist. Neu
ist kein Schlüsselwort in Kotlin. Dies macht unseren Quellcode beim Erstellen einer Klasseninstanz prägnant. Beachten Sie jedoch, dass die Instantiierung einer Kotlin-Klasse in Java die Neu
Stichwort.
// In einer Java-Datei Book book = new Book ()
Sehen wir uns an, wie Sie unserer Klasse einen Konstruktor und Eigenschaften hinzufügen. Aber zuerst sehen wir eine typische Klasse in Java:
/ * Java * / public class Book private Zeichenfolge title; private lange isbn; öffentliches Buch (String title, Long isbn) this.title = title; this.isbn = isbn; public String getTitle () return title; public void setTitle (String title) this.title = title; public Long getIsbn () return isbn; public void setIsbn (Long isbn) this.isbn = isbn;
Blick auf unsere Buch
Modellklasse oben haben wir Folgendes:
Titel
und isbn
Nun schauen wir uns an, wie wir stattdessen den vorhergehenden Code in Kotlin schreiben können:
/ * Kotlin * / class Book var title: String var isbn: Long-Konstruktor (title: String, isbn: Long) this.title = title this.isbn = isbn
Eine hübsche ordentliche Klasse! Wir haben jetzt die Anzahl der Codezeilen von 20 auf nur noch 9 reduziert Konstrukteur()
Funktion heißt a sekundärer Konstruktor in Kotlin. Dieser Konstruktor entspricht dem Java-Konstruktor, den wir beim Instanziieren einer Klasse aufgerufen haben.
In Kotlin gibt es kein Konzept eines Feldes, mit dem Sie vielleicht vertraut sind. Stattdessen wird das Konzept der "Eigenschaften" verwendet. Zum Beispiel haben wir zwei veränderliche Eigenschaften (Lese- und Schreibzugriff), die mit der var
Stichwort: Titel
und isbn
in dem Buch
Klasse. (Wenn Sie eine Auffrischung der Variablen in Kotlin benötigen, besuchen Sie bitte den ersten Beitrag dieser Serie: Variablen, Basistypen und Arrays.).
Eine erstaunliche Sache ist, dass die Getter und Setter für diese Eigenschaften vom Kotlin-Compiler automatisch unter der Haube generiert werden. Beachten Sie, dass wir für diese Eigenschaften keine Sichtbarkeitsmodifizierer angegeben haben. Standardmäßig sind sie öffentlich. Sie können also von überall aus auf sie zugreifen.
Schauen wir uns eine andere Version derselben Klasse in Kotlin an:
Klassenbuchkonstruktor (title: String, isbn: Long) var title: String var isbn: Long init this.title = title this.isbn = isbn
In diesem Code haben wir den sekundären Konstruktor entfernt. Stattdessen haben wir im Klassenheader einen Konstruktor namens a deklariert primärer Konstruktor. Ein primärer Konstruktor hat keinen Platz zum Platzieren eines Codeblocks, also verwenden wir den drin
Modifizierer, um eingehende Parameter vom primären Konstruktor zu initialisieren. Notiere dass der drin
Codeblock wird sofort ausgeführt, wenn die Klasseninstanz erstellt wird.
Wie Sie sehen können, enthält unser Code immer noch viele Boilerplates. Lassen Sie uns weiter reduzieren:
Klassenbuchkonstruktor (var title: String, var isbn: Long)
Unsere Buch
Klasse ist jetzt nur noch eine Codezeile. Das ist echt cool! Beachten Sie, dass wir in der Parameterliste des primären Konstruktors unsere veränderbaren Eigenschaften definiert haben: Titel
und isbn
direkt im primären Konstruktor mit der var
Stichwort.
Wir können auch den Klasseneigenschaften direkt im Konstruktor Standardwerte hinzufügen.
Klassenbuchkonstruktor (var title: String = "Standardwert", var isbn: Long)
In der Tat können wir auch das weglassen Konstrukteur
Schlüsselwort, aber nur, wenn es keinen Sichtbarkeitsmodifikator hat (Öffentlichkeit
, Privatgelände
, oder geschützt
) oder Anmerkungen.
Klassenbuch (var title: String = "Standardwert", var isbn: Long)
Eine sehr ordentliche Klasse, muss ich sagen!
Wir können jetzt eine Klasseninstanz wie folgt erstellen:
val book = Buch ("Ein Lied aus Eis und Feuer", 9780007477159) val book2 = Buch (1234) // verwendet den Standardwert der Titeleigenschaft
In Kotlin können wir eine Eigenschaft durch das Klassenobjekt erhalten Buch
, gefolgt von einem Punktseparator .
, dann der Eigenschaftsname Titel
. Diese prägnante Art des Zugriffs auf Eigenschaften wird aufgerufen Eigenschaftszugriffssyntax. Mit anderen Worten, wir müssen die Eigenschafts-Getter-Methode nicht aufrufen, um auf den Setter zuzugreifen, oder eine Eigenschaft in Kotlin zu setzen, wie in Java.
println (book.title) // "Ein Lied von Eis und Feuer"
Weil der isbn
Eigenschaft wird mit deklariert var
Mit dem Schlüsselwort (Lese- und Schreibzugriff) können Sie den Eigenschaftswert auch mit dem Zuweisungsoperator ändern =
.
book.isbn = 1234 println (book.isbn) // 1234
Sehen wir uns ein anderes Beispiel an:
class Book (Variablentitel: String, val isbn: Long) val book = Buch ("Ein Lied von Eis und Feuer", 9780007477159) book.isbn = 1234 // Fehler: schreibgeschützte Eigenschaft book.title = "Dinge fallen auseinander "// Titel mit Wert neu zugewiesen
Hier haben wir das aktualisiert isbn
Parameter, der unveränderlich (schreibgeschützt) ist, stattdessen mithilfe von val
Stichwort. Wir haben eine Klasseninstanz instanziiert Buch
und das neu zugewiesen Titel
Eigenschaft den Wert "Dinge fallen auseinander". Beachten Sie das, als wir versuchten, das neu zuzuweisen isbn
Eigenschaftswert in 1234
, der Compiler beschwerte sich. Dies liegt daran, dass die Eigenschaft unveränderlich ist, nachdem sie mit definiert wurde val
Stichwort.
Beachten Sie dies, indem Sie einen Parameter mit der var
Der Kotlin-Compiler (hinter den Kulissen) hat uns dabei geholfen, die Property-Accessoren zu erzeugen: Getter und Setter. Wenn du benutzt val
, es wird nur der Getter generiert.
/ * Kotlin * / class Book (Variablentitel: String, Wert isbn: Long)
Dies bedeutet, dass Java-Aufrufer das Eigenschaftsfeld einfach abrufen oder festlegen können, indem sie die Setter- oder Getter-Methode der Eigenschaft aufrufen. Beachten Sie, dass dies vom Modifikator abhängt, der zur Definition der Kotlin-Eigenschaft verwendet wird: var
oder val
.
/ * Java * / Book book = neues Buch ("Ein Lied von Eis und Feuer", 9780385474542) println (book.getTitle ()) // "Ein Lied von Eis und Feuer" book.setTitle ("Dinge fallen auseinander") // setzt einen neuen Wert println (book.getTitle ()) // "Dinge fallen auseinander" book.getIsbn () // 9780385474542 book.setIsbn (4545454) // kann nicht kompiliert werden
In diesem Abschnitt zeige ich Ihnen, wie Sie benutzerdefinierte Accessoren (Getter und Setter) für eine Eigenschaft in Kotlin erstellen, wenn Sie möchten. Das Erstellen eines benutzerdefinierten Setters kann hilfreich sein, wenn Sie einen Wert überprüfen oder überprüfen möchten, bevor er auf eine Klasseneigenschaft gesetzt wird. Ein benutzerdefinierter Eigenschafts-Getter kann nützlich sein, wenn Sie den zurückgegebenen Wert ändern oder ändern möchten.
Da wir unseren eigenen benutzerdefinierten Getter oder Setter für eine Eigenschaft erstellen möchten, müssen wir diese Eigenschaft im Klassenhauptteil anstelle des Konstruktorkopfes definieren.
Klassenbuch (Wert isbn: Long) var title = "Standardwert"
Deshalb haben wir die veränderliche verschoben (Lese- und Schreibzugriff). Titel
Eigenschaft in den Klassenhauptteil und gab ihm einen Standardwert (sonst würde er nicht kompilieren).
class Book (Wert isbn: Long) var title = "Standardwert" set (value) if (! value.isNotEmpty ()) throw IllegalArgumentException ("Titel darf nicht leer sein") Feld = Wert
Sie sehen, wir haben unsere eigene Setzermethode definiert Set (Wert)
für die Titel
Direkt unter dem Eigenschaftendefinitions-Hinweis, dass Sie dies nicht ändern können einstellen()
Methodensignatur, da dies der Compiler als benutzerdefinierte Eigenschaftssetzer-Funktion erwartet.
Der Parameter Wert
an den übergeben einstellen
Die Methode stellt den tatsächlichen Wert dar, der der Eigenschaft von Benutzern zugewiesen wurde. Sie können den Parameternamen jedoch ändern, wenn Sie möchten Wert
ist sehr bevorzugt. Wir haben das validiert Wert
Überprüfen Sie, ob der Wert leer ist. Wenn leer, stoppen Sie die Ausführung und geben Sie eine Ausnahme aus. Andernfalls weisen Sie den Wert einem speziellen Wert zu Feld
Variable.
Dieses Besondere Feld
variables Feld innerhalb der einstellen
method ist ein Alias für das Hintergrundfeld der Eigenschaft. Ein Hintergrundfeld ist nur ein Feld, das von Eigenschaften verwendet wird, wenn Sie diese Felddaten ändern oder verwenden möchten. nicht wie Wert
, Du kannst dieses Special nicht umbenennen Feld
Variable.
Es ist sehr einfach, einen benutzerdefinierten Getter für eine Immobilie in Kotlin zu erstellen.
class Book (Wert isbn: Long) var title = "Standardwert" //… set-Methode get () return field.toUpperCase ()
In der erhalten
Methode, wir geben einfach eine modifizierte zurück Feld
-In unserem Fall haben wir den Buchtitel in Großbuchstaben zurückgegeben.
val book = Book (9780007477159) book.title = "Ein Lied von Eis und Feuer" println (book.title) // "EIN SONG VON EIS UND FEUER" println (book.isbn) // 9780007477159
Beachten Sie, dass wir jedes Mal einen Wert auf den Wert setzen Titel
Eigentum, sein einstellen
Methodenblock wird ausgeführt - das Gleiche gilt für erhalten
Methode jedes Mal, wenn wir es abrufen.
Wenn Sie mehr über Elementfunktionen für eine Kotlin-Klasse erfahren möchten (die Art von Funktion, die in einer Klasse, einem Objekt oder einer Schnittstelle definiert ist), besuchen Sie den Beitrag Mehr Spaß mit Funktionen in dieser Serie.
Wie ich bereits besprochen habe, gibt es in Kotlin zwei Arten von Konstruktoren: primäre und sekundäre. Wir haben die Freiheit, beide in einer einzigen Klasse zu kombinieren - wie Sie im folgenden Beispiel sehen können:
Klasse Car (Wertname: String, Wert: Val PlateNo: String) var new: Boolean = true Konstruktor (Name: String, PlateNo: String, Neu: Boolean): this (Name, PlateNo) this.new = new
Beachten Sie, dass wir keine Eigenschaften innerhalb eines sekundären Konstruktors deklarieren können, wie dies beim primären Konstruktor der Fall war. Wenn wir dies tun wollen, müssen wir es im Klassenhauptteil deklarieren und dann im sekundären Konstruktor initialisieren.
Im obigen Code setzen wir den Standardwert von Neu
Eigenschaft für die Klasse Auto
(merken, Neu
ist kein Schlüsselwort in Kotlin) - Wir können dann den sekundären Konstruktor verwenden, um ihn zu ändern, wenn wir möchten. In Kotlin muss jeder sekundäre Konstruktor den primären Konstruktor oder einen anderen sekundären Konstruktor aufrufen, der den primären Konstruktor aufruft - wir verwenden den diese
Stichwort, um das zu erreichen.
Beachten Sie auch, dass wir innerhalb einer Klasse mehrere sekundäre Konstruktoren haben können.
Klasse Car (Wertname: String, WertetellerNr: String) var neu: Boolean? = null var color: String = "" Konstruktor (Name: String, PlattenNr: String, neu: Boolean): this (Name, Plattennr.) this.new = new Konstruktor (Name: String, Plattennr .: String, neu: Boolean) , color: String): this (name, plateNo, new) this.colour = color
Wenn eine Klasse eine Superklasse erweitert, können wir die Super
Schlüsselwort (ähnlich wie Java), um den Superklassenkonstruktor aufzurufen (die Vererbung in Kotlin wird in einem zukünftigen Beitrag besprochen).
// ruft direkt den primären Konstruktor val car1 = Car ("Peugeot 504", "XYZ234") auf // // ruft direkt die 1. Sekunde auf Konstruktor val car2 = Auto ("Peugeot 504", "XYZ234", false) // ruft direkt die letzte Sekunde auf. Konstruktor val car3 = Auto ("Peugeot 504", "XYZ234", falsch, "grau")
Wie ich bereits sagte, müssen wir den Konstruktor in einer Klasse explizit mit einem Modifizierer für die Sichtbarkeit versehen Konstrukteur
Standardmäßig sind Konstruktoren öffentlich.
Klasse Auto-privater Konstruktor (Wertname: String, WertetellerNr: String) //…
Hier haben wir den Konstruktor als privat deklariert. Dies bedeutet, dass Benutzer ein Objekt nicht direkt mit seinem Konstruktor instanziieren können. Dies kann nützlich sein, wenn Benutzer stattdessen eine andere Methode (eine Factory-Methode) aufrufen möchten, um Objekte indirekt anzulegen.
In Kotlin wird der oberste Typ in der Typhierarchie aufgerufen Irgendein
. Dies entspricht Java Objekt
Art. Dies bedeutet, dass alle Klassen in Kotlin explizit von der Irgendein
Typ, einschließlich String
, Int
, Doppelt
, und so weiter. Das Irgendein
Typ enthält drei Methoden: gleich
, toString
, und Hash-Code
.
Wir können auch die nutzen Nichts
Klasse in Kotlin in Funktionen, die immer eine Ausnahme zurückgeben - mit anderen Worten für Funktionen, die nicht normal beendet werden. Wenn eine Funktion zurückkehrt Nichts
, dann wissen wir, dass es eine Ausnahme auslösen wird. In Java existiert kein gleichwertiger Typ dieser Art.
fun throwException (): Nichts Ausnahme werfen ("Ausnahmemeldung)
Dies kann hilfreich sein, wenn Sie das Verhalten der Fehlerbehandlung in Ihren Gerätetests testen.
Sichtbarkeitsmodifizierer helfen uns, die Zugänglichkeit unserer API für die Öffentlichkeit einzuschränken. Wir können verschiedene Sichtbarkeitsmodifikatoren für Klassen, Schnittstellen, Objekte, Methoden oder Eigenschaften bereitstellen. Kotlin stellt uns vier Sichtbarkeitsmodifizierer zur Verfügung:
Dies ist die Standardeinstellung. Auf jede Klasse, Funktion, Eigenschaft, Schnittstelle oder jedes Objekt, das diesen Modifikator enthält, kann von überall aus zugegriffen werden.
Eine Funktion, Schnittstelle oder Klasse der obersten Ebene, die als deklariert ist Privatgelände
kann nur innerhalb derselben Datei aufgerufen werden.
Jede deklarierte Funktion oder Eigenschaft Privatgelände
Innerhalb einer Klasse, eines Objekts oder einer Schnittstelle können nur andere Mitglieder derselben Klasse, dieses Objekts oder derselben Schnittstelle sichtbar sein.
Klassenkonto privater Wert: doppelt = 0,0
Das geschützt
Der Modifizierer kann nur auf Eigenschaften oder Funktionen innerhalb einer Klasse, eines Objekts oder einer Schnittstelle angewendet werden. Er kann nicht auf Funktionen, Klassen oder Schnittstellen der obersten Ebene angewendet werden. Auf Eigenschaften oder Funktionen mit diesem Modifikator kann nur innerhalb der Klasse, in der sie definiert sind, und in Unterklassen zugegriffen werden.
In einem Projekt mit einem Modul (Gradle- oder Maven-Modul) werden eine Klasse, ein Objekt, eine Schnittstelle oder eine Funktion mit der angegeben intern
Modifier, der innerhalb dieses Moduls deklariert ist, ist nur innerhalb dieses Moduls zugänglich.
interne Klasse Konto Wertbetrag: Doppel = 0,0
Casting bedeutet, ein Objekt eines anderen Typs zu nehmen und in einen anderen Objekttyp umzuwandeln. In Java verwenden wir beispielsweise die Beispielvon
Operator, um festzustellen, ob ein bestimmter Objekttyp von einem anderen Typ ist, bevor wir ihn umsetzen.
/ * Java * / if (Forminstanz eines Kreises) Kreiskreis = (Kreis) Form; Kreis.Kalikonumfang (3.5);
Wie Sie sehen, haben wir geprüft, ob gestalten
Beispiel ist Kreis
, und dann müssen wir das explizit werfen gestalten
Verweis auf a Kreis
tippen, so dass wir Methoden der aufrufen können Kreis
Art.
Eine weitere tolle Sache an Kotlin ist die Klugheit seines Compilers, wenn es ums Casting geht. Lassen Sie uns jetzt eine Version in Kotlin sehen.
/ * Kotlin * / if (Form ist Kreis) shape.calCircumference (3.5)
Ziemlich ordentlich! Der Compiler ist klug zu wissen, dass die ob
Block wird nur ausgeführt, wenn der gestalten
Objekt ist eine Instanz von Kreis
-so wird der gießmechanismus für uns unter der haube ausgeführt. Wir können jetzt leicht Eigenschaften oder Funktionen des aufrufen Kreis
tippen Sie in das ob
Block.
if (Shape ist Kreis && Shape.hasRadius ()) println ("Kreisradius ist Shape.radius")
Hier die letzte Bedingung nach dem &&
in dem ob
Der Header wird nur aufgerufen, wenn die erste Bedingung erfüllt ist wahr
. Wenn die gestalten
ist kein Kreis
, dann wird die letzte Bedingung nicht bewertet.
Wir können die verwenden wie
Operator (oder unsichere Besetzung Operator), um explizit eine Referenz eines Typs auf einen anderen Typ in Kotlin umzuwandeln.
val circle = Form als Circle circle.calCumfum (4)
Wenn der explizite Casting-Vorgang nicht zulässig ist, beachten Sie, dass a ClassCastException
wird geworfen. Um zu verhindern, dass beim Casting eine Ausnahme ausgelöst wird, können Sie das verwenden sichere Besetzung Operator (oder nullfähiger Cast-Operator) wie?
.
Val Circle: Kreis? = Form wie? Kreis
Das wie?
Der Operator wird versuchen, den gewünschten Typ zu übernehmen, und er kehrt zurück Null
Wenn der Wert nicht umgewandelt werden kann, anstatt eine Ausnahme auszulösen. Denken Sie daran, dass ein ähnlicher Mechanismus in dieser Serie im Abschnitt "Nullability" in "Nullability", "Loops" und "Condition" beschrieben wurde. Lesen Sie dort für eine Auffrischung nach.
Objekte in Kotlin sind JavaScript-Objekten ähnlicher als Java-Objekte. Beachten Sie, dass ein Objekt in Kotlin keine Instanz einer bestimmten Klasse ist!
Objekte sind Klassen sehr ähnlich. Hier einige Eigenschaften von Objekten in Kotlin:
drin
Block.Lassen Sie uns nun herausfinden, wie ein Objekt erstellt wird.
object Singleton fun myFunc (): Einheit // etwas tun
Wir platzieren die Objekt
Schlüsselwort vor dem Namen des Objekts, das wir erstellen möchten. Tatsächlich erstellen wir Singletons, wenn wir Objekte in Kotlin mithilfe von erstellen Objekt
Konstrukt, da nur eine Instanz eines Objekts vorhanden ist. Sie erfahren mehr darüber, wenn wir die Interoperabilität von Objekten mit Java besprechen.
Ein Singleton ist ein Software-Entwurfsmuster, das garantiert, dass eine Klasse nur eine Instanz hat und von dieser Klasse ein globaler Zugriffspunkt für sie bereitgestellt wird. Jedes Mal, wenn mehrere Klassen oder Clients die Klasse anfordern, erhalten sie dieselbe Instanz der Klasse. Sie können meinen Beitrag über das Singleton-Muster in Java überprüfen, um mehr darüber zu erfahren.
Sie können auf das Objekt oder das Singleton überall in Ihrem Projekt zugreifen, solange Sie das Paket importieren.
Singleton.myFunc ()
Wenn Sie ein Java-Coder sind, erstellen wir normalerweise Singletons:
öffentliche Klasse Singleton privates statisches Singleton INSTANCE = null; // andere Instanzvariablen können hier private sein Singleton () ; public static synchronized Singleton getInstance () if (INSTANCE == null) INSTANCE = new Singleton (); return (INSTANZ); // andere Instanzmethoden können folgen
Wie Sie sehen können, verwenden Sie den Kotlin Objekt
construct macht es einfach, Singletons zu erstellen.
Objekte in Kotlin können auch zum Erstellen von Konstanten verwendet werden. Normalerweise erstellen wir in Java Konstanten in einer Klasse, indem wir sie zu einem öffentlichen statischen Abschlussfeld wie folgt machen:
öffentliche Abschlussklasse APIConstants public static final String baseUrl = "http://www.myapi.com/"; private APIConstants ()
Dieser Code in Java kann wie folgt in Kotlin umgewandelt werden:
Paket com.chike.kotlin.constants object APIConstants val baseUrl: String = "http://www.myapi.com/"
Hier haben wir die Konstante erklärt APIConstanten
mit einer Immobilie baseUrl
in einem Paket com.chike.kotlin.constants
. Unter der Haube ein privates statisches Java-Endmitglied baseUrl
wird für uns erstellt und mit der String-URL initialisiert.
Um diese Konstante in einem anderen Paket in Kotlin zu verwenden, importieren Sie das Paket einfach.
import com.chike.kotlin.constants.APIConstants APIConstants.baseUrl
Kotlin konvertiert ein Objekt in eine letzte Java-Klasse unter der Haube. Diese Klasse hat ein privates statisches Feld BEISPIEL
die eine einzelne Instanz (ein Singleton) der Klasse enthält. Der folgende Code zeigt, wie einfach ein Kotlin-Objekt von Java aus aufgerufen werden kann.
/ * Java * / Singleton.INSTANCE.myFunc ()
Hier wird eine Java-Klasse aufgerufen Singleton
wurde mit einem öffentlichen statischen Final Member erstellt BEISPIEL
, einschließlich einer öffentlichen abschließenden Funktion myFunc ()
.
Um die Objektfunktion oder -eigenschaft in Kotlin zu einem statischen Member der generierten Java-Klasse zu machen, verwenden wir die @JvmStatic
Anmerkung. So verwenden Sie es:
object Singleton @JvmStatic fun myFunc (): Einheit // etwas tun
Durch Anwenden der @JvmStatic
Anmerkung zu myFunc ()
, Der Compiler hat daraus eine statische Funktion gemacht.
Java-Aufrufer können es jetzt wie einen normalen statischen Member-Aufruf aufrufen. Beachten Sie, dass die Verwendung der BEISPIEL
Das statische Feld, um Mitglieder anzurufen, funktioniert weiterhin.
/ * Java * / Singleton.myFunc ()
Jetzt haben wir verstanden, welche Objekte sich in Kotlin befinden. Lassen Sie uns in eine andere Art von Objekten eintauchen, die als Begleitobjekte bezeichnet werden.
Da Kotlin keine statischen Klassen, Methoden oder Eigenschaften wie in Java unterstützt, hat das Kotlin-Team uns eine leistungsfähigere Alternative zur Verfügung gestellt Begleitobjekte. Ein Begleitobjekt ist im Wesentlichen ein Objekt, das zu einer Klasse gehört. Diese Klasse wird als Begleitklasse des Objekts bezeichnet. Das bedeutet auch, dass die von mir genannten Merkmale für Objekte auch für Begleitobjekte gelten.
Ähnlich wie bei statischen Methoden in Java ist ein Begleitobjekt nicht mit einer Klasseninstanz verknüpft, sondern mit der Klasse selbst - beispielsweise einer statischen Factory-Methode, die die Aufgabe hat, eine Klasseninstanz zu erstellen.
Klasse Privater Personenkonstruktor (var Vorname: String, Var Nachname: String) Begleitobjekt fun create (Vorname: String, Nachname: String): Person = Person (Vorname, Nachname)
Hier haben wir den Konstruktor gemacht Privatgelände
-Dies bedeutet, dass Benutzer außerhalb der Klasse keine Instanz direkt erstellen können. In unserem Begleitobjektblock haben wir eine Funktion erstellen()
, was schafft ein Person
Objekt und gibt es zurück.
Begleiter
Objektinstanziierung ist faul. Mit anderen Worten, es wird nur instanziiert, wenn es das erste Mal benötigt wird. Die Instantiierung von a Begleiter
Objekt passiert, wenn eine Instanz von Begleiter
Klasse wird erstellt oder die Begleiter
Auf Objektmitglieder wird zugegriffen.
Sehen wir uns an, wie Sie eine begleitende Objektfunktion in Kotlin aufrufen.
val person = Person.create ("Cersei", "Lannister") println (person.firstName) // druckt "Cersei"
Wie Sie sehen, ist dies wie ein normales Aufrufen einer statischen Methode in Java. Mit anderen Worten, wir rufen einfach die Klasse an und dann das Mitglied. Beachten Sie, dass wir außer Funktionen auch Eigenschaften in unserem Begleitobjekt haben können.
class Person privater Konstruktor (var Vorname: String, Var Nachname: String) init count ++ Begleitobjekt var count: Int = 0 fun create (Vorname: String, Nachname: String): Person = Person (Vorname, Nachname) init println ("Objekt für Personenobjekt erstellt")
Beachten Sie auch, dass die Begleiter
Die Klasse hat uneingeschränkten Zugriff auf alle Eigenschaften und Funktionen, die in ihrem Begleitobjekt deklariert sind, während ein Begleitobjekt nicht auf die Klassenmitglieder zugreifen kann. Wir können eine haben drin
Code-Block in einem Begleiter
object - Dies wird sofort aufgerufen, wenn das Begleitobjekt erstellt wird.
Person.create ("Arya", "Stark") Person.create ("Daenerys", "Targaryen") println (Person.count)
Das Ergebnis der Ausführung des obigen Codes ist:
Personenbegleitobjekt erstellt 2
Denken Sie daran, nur eine einzelne Instanz einer Klasse Begleiter
Objekt kann immer existieren.
Wir können unser Begleitobjekt auch mit einem Namen versehen.
//… Begleitobjekt Factory var count: Int = 0 Spaß beim Erstellen (firstName: String, lastName: String): Person = Person (firstName, lastName) //…
Hier haben wir ihm einen Namen gegeben Fabrik
. Wir können es dann in Kotlin so nennen:
Person.Factory.create ("Petyr", "Baelish")
Dieser Stil ist wortreich, daher wird die Beibehaltung des vorherigen Weges bevorzugt. Dies kann jedoch nützlich sein, wenn Sie eine begleitende Objektfunktion oder -eigenschaft von Java aus aufrufen.
Wie bereits erwähnt, können Begleitobjekte wie Objekte auch Eigenschaften oder Funktionen enthalten, Schnittstellen implementieren und sogar eine Klasse erweitern.
Schnittstelle PersonFactory fun create (Vorname: String, Nachname: String): Person Klasse Person Private Konstruktor (var Vorname: String, Var Nachname: String) Begleitobjekt: PersonFactory Überschreibe fun create (Vorname: String, Nachname: String) : Person Rückgabe Person (Vorname, Nachname)
Hier haben wir eine Schnittstelle PersonFactory
mit nur einem einzigen erstellen()
Funktion. Blick auf unsere neue modifizierte Begleiter
Objekt implementiert es jetzt diese Schnittstelle (Sie werden in einem späteren Beitrag mehr über Schnittstellen und Vererbung in Kotlin erfahren).
Unter der Haube werden Begleitobjekte ähnlich wie ein Kotlin-Objekt kompiliert. In unserem eigenen Fall werden zwei Klassen für uns generiert: ein Finale Person
Klasse und eine innere statische Abschlussklasse Person $ Begleiter
.
Das Person
Klasse enthält ein letztes statisches Member namens Begleiter
-Dieses statische Feld ist ein Objekt des Person $ Begleiter
innere Klasse. Das Person $ Begleiter
Die innere Klasse hat auch eigene Mitglieder, und eines davon ist eine öffentliche Schlussfunktion erstellen()
.
Beachten Sie, dass wir unserem Begleitobjekt keinen Namen gegeben haben, also die generierte statische innere Klasse Begleiter
. Wenn wir ihm einen Namen gegeben hätten, wäre der generierte Name der Name, den wir ihm in Kotlin gegeben haben.
/ * Java * / Person person = Person.Companion.create ("Jon", "Snow");
Das Begleitobjekt in Kotlin hat hier keinen Namen, daher verwenden wir den Namen Begleiter
wird vom Compiler für Java-Aufrufer zur Verfügung gestellt.
Das @JvmStatic
Anmerkung, die auf ein Companion-Objektelement angewendet wird, funktioniert ähnlich wie ein normales Objekt.
Ähnlich wie Erweiterungsfunktionen die Funktionalität einer Klasse erweitern können, können wir auch die Funktionalität eines Begleitobjekts erweitern. (Wenn Sie sich über die Erweiterungsfunktionen in Kotlin informieren möchten, besuchen Sie das Lernprogramm "Erweiterte Funktionen" in dieser Serie.).
class ClassA Begleitobjekt fun ClassA.Companion.extFunc () //… Implementierung ausführen ClassA.extFunc ()
Hier haben wir eine Erweiterungsfunktion definiert extFunc ()
auf dem Begleitobjekt ClassA.Companion
. Mit anderen Worten, extfunc ()
ist eine Erweiterung des Begleitobjekts. Dann können wir die Erweiterung so bezeichnen, als wäre sie eine Member-Funktion des Companion-Objekts (es ist keine!).
Hinter den Kulissen erstellt der Compiler eine statische Utility-Funktion extFunc ()
. Das Empfängerobjekt als Argument für diese Utility-Funktion lautet Klasse A $ Begleiter
.
In diesem Lernprogramm haben Sie grundlegende Klassen und Objekte in Kotlin kennen gelernt. Wir haben über den Unterricht folgende Themen behandelt:
Außerdem haben Sie erfahren, wie Objekte und Begleitobjekte in Kotlin Ihre statischen Methoden, Konstanten und Singletons, die Sie in Java codieren, leicht ersetzen können. Aber das ist nicht alles! Es