Kotlin von Grund auf Klassen und Objekte

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. 

1. Klassen

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 ()

Klassenkonstruktoren und Eigenschaften

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:

  • zwei Felder: Titel und isbn
  • ein einzelner Konstruktor
  • Getter und Setter für die beiden Felder (glücklicherweise kann IntelliJ IDEA uns dabei helfen, diese Methoden zu generieren)

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

Eigenschaften aufrufen und einstellen 

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. 

Java-Interoperabilität

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

Kundenspezifische Getter und Setter

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.  

Einen benutzerdefinierten Setter erstellen

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.

Einen benutzerdefinierten Getter erstellen

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. 

Mehr zu Konstruktoren

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. 

2. Any und Nothing Types

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 StringInt, Doppelt, und so weiter. Das Irgendein Typ enthält drei Methoden: gleichtoString, 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.   

3. Sichtbarkeitsmodifikatoren

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:

Öffentlichkeit

Dies ist die Standardeinstellung. Auf jede Klasse, Funktion, Eigenschaft, Schnittstelle oder jedes Objekt, das diesen Modifikator enthält, kann von überall aus zugegriffen werden.

Privatgelände 

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

Geschützt

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. 

Intern 

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

4. Smart Casting

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. 

5. Explizite Besetzung

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.

6. Objekte

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:

  • Sie können Eigenschaften, Methoden und eine haben drin Block.
  • Diese Eigenschaften oder Methoden können Sichtbarkeitsmodifizierer aufweisen.
  • Sie können keine Konstruktoren haben (primär oder sekundär).
  • Sie können andere Klassen erweitern oder eine Schnittstelle implementieren.

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

Java-Interoperabilität

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 ()

7. Begleitobjekte

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. 

Begleitobjekt erstellen

Ä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. 

Aufrufen einer Companion-Objektfunktion

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). 

Java-Interoperabilität

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. 

Begleitobjekt-Erweiterungen

Ä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

Fazit

In diesem Lernprogramm haben Sie grundlegende Klassen und Objekte in Kotlin kennen gelernt. Wir haben über den Unterricht folgende Themen behandelt:

  • Klassenerstellung
  • Konstruktoren
  • Eigenschaften
  • Sichtbarkeitsmodifikatoren
  • Smart Casting
  • explizites Gießen 

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