Die Sichtbarkeit von Java und Kotlin ist etwas unterschiedlich.
Definieren wir eine Hundeklasse, die die Tierklasse in Kotlin erbt.
open class Animal { //Fügen Sie open hinzu, um es zu einer vererbbaren Klasse zu machen
open fun greet() { //Fügen Sie open hinzu, um es zu einer überschreibbaren Funktion zu machen
}
}
class Dog: Animal() { //Doppelpunkt gefolgt vom Namen der Elternklasse
override fun greet() { //Überschreibungsmodifikator hinzufügen
println("Bow wow")
}
}
Beim Erben einer Klasse
Klasse Unterklassenname
: Schreiben als Superklassenkonstruktor
.
Schauen wir uns den Fall an, in dem der Konstruktor Argumente benötigt.
open class Animal(val name: String) {
open fun greet() {
}
}
//Argument des Hundekonstruktors`name`An den Konstruktor der Tierklasse
class Dog(name: String): Animal(name) {
override fun greet() {
println("Bow wow")
}
}
Kotlin hat keinen statischen Modifikator.
Wenn Sie statische Elemente und statische Funktionen in Kotlin-Klassen verarbeiten möchten, Verwenden Sie ein Begleitobjekt.
Was ist ein Begleitobjekt? Eine spezielle Singleton-Instanz.
class Dog {
companion object {
val ancestorName: String = "wolf"
}
fun greet() {
println("Bow wow")
}
}
val ancestor = Dog.ancestorName
Ich habe eine Eigenschaft namens "ancestorName" im "Companion-Objekt" definiert.
Um auf diese Eigenschaft zuzugreifen, greifen Sie auf Dog.ancestorName
zu, als wäre es ein statisches Mitglied.
Kotlin verfügt über einen Mechanismus zur einfachen Implementierung eines Singletons.
object ResourceManager {
fun clean() {
// ...
}
}
ResourceManager.clean()
Sie können eine Singleton-Klasse nach dem Schlüsselwort object
definieren.
Sie können Eigenschaften und Funktionen wie eine reguläre Klasse definieren.
In der Objektdeklaration kann nicht nur der Konstruktor definiert werden.
Verwenden Sie den Klassennamen, um auf eine Singleton-Instanz zuzugreifen.
Ähnlich wie beim Zugriff auf statische Elemente in Java.
Sie implementieren oft einfache Klassen zum Speichern von Daten, oder?
data class Point(val x : Int,
val y: Int) {
}
Definieren Sie die Klasse nach dem Schlüsselwort "data". Die Datenklasse berücksichtigt alle im Primärkonstruktor deklarierten Eigenschaften mit den folgenden Funktionen.
Außerdem wird die Kopierfunktion automatisch generiert. Es kann kopiert werden, während eine Eigenschaft geändert wird.
fun moveTo(point: Point, newX: Int): Point {
return point.copy(x = newX)
}
Deklarieren Sie alle Eigenschaften mit val, machen Sie die Klasse unveränderlich, Sie können problemlos eine Kopie mit neu geschriebenen Werten erstellen.
Die versiegelte Klasse ist eine Klasse, die nur innerhalb derselben Datei vererbt werden kann.
sealed class Animal {
}
class Dog: Animal() {
}
class Cat: Animal() {
}
fun greet(animal: Animal) = when(animal) {
is Dog -> "bow wow"
is Cat -> "meow meow"
// else ->Keine Notwendigkeit für einen anderen Fall!
}
Beachten Sie, wenn in der Begrüßungsfunktion oben. Es gibt keinen anderen Fall. Dies ist der Effekt der versiegelten Klasse.
Wenn Sie in Java eine Klasse innerhalb einer Klasse definieren, ändert sich die Bedeutung abhängig davon, ob der statische Modifikator hinzugefügt wird oder nicht. Vergleichen wir es mit Kotlins Beschreibungsmethode.
Java | Kotlin |
---|---|
static class A | class A |
class A | inner class A |
Kotlin ist standardmäßig eingestellt
Synonym für Javas verschachtelte Klasse mit static
.
Kotlin-Eigenschaften können in einer Zeile deklariert werden. Es ist möglich, den Getter bzw. den Setter anzupassen.
class Dog(name: String) {
var name: String = name
get() { //Kundenspezifischer Getter
//Feldvariablen sind in Gettern verfügbar
//Dieser Getter ist im Namen"Chan"Rückkehr mit
return field + "Chan"
}
set(value) { //Benutzerdefinierter Setter
//Setter gibt den Argumentnamen an
//Dieser Setter entfernt Leerzeichen von der Vorderseite des Namens und setzt sie in das Feld
field = value.trimMargin()
}
}
Kotlin-Klassen sind standardmäßig nicht vererbbar. Es gibt einen Mechanismus, um die Funktion ohne Vererbung zu erweitern.
Mit einer Schnittstelle namens Movable Ich habe eine MovableImpl-Klasse definiert, die Movable implementiert.
interface Movable {
fun walk()
fun run()
fun currentCount(): Int
}
class MovableImpl: Movable {
private var count: Int = 0
override fun walk() {
this.count += 1
}
override fun run() {
this.count += 3
}
override fun currentCount(): Int = this.count
}
Definieren Sie eine Hundeklasse, die die Funktionalität dieses Movable erweitert.
class Dog(movable: MovableImpl): Movable by movable {
}
Geben Sie nach dem Schlüsselwort "by" die Instanz an, an die die Movable-Funktionalität delegiert wird. Diese Hundeklasse hat keine Implementierung für die Movable-Oberfläche. Es wird automatisch an MovableImpl delegiert.
val dog = Dog(MovableImpl())
dog.walk()
dog.walk()
dog.run()
println(dog.currentCount()) // 5
Sie können das Verhalten von Property Getter und Setter delegieren. Definieren Sie eine Klasse wie diese.
class Dog {
var name: String by NameFormatter()
}
class Cat {
var name: String by NameFormatter()
}
Sowohl die Hunde- als auch die Katzenklasse haben eine Eigenschaft namens name.
Beide geben by
gefolgt von NameFormatter an.
Versuchen Sie, den folgenden Code auszuführen.
val dog = Dog()
dog.name = "Pochi"
println(dog.name) //Pochi-Chan
val cat = Cat()
cat.name = "Marmor"
println(cat.name) //Tama-Chan
In beiden Fällen werden die Leerzeichen aus der dem Namen zugewiesenen Zeichenfolge entfernt. Im Getter wird "chan" als Suffix hinzugefügt.
Schauen wir uns nun die Implementierung von NameFormatter an.
class NameFormatter {
private var name: String = ""
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return this.name + "Chan"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
this.name = value.trimStart()
}
}
Implementieren Sie die Methoden "getValue" und "setValue" nach dem Schlüsselwort "operator".
Auf diese Weise kann das Verhalten der Eigenschaft nach außen delegiert werden.
Recommended Posts