Kotlin vom Lernen zu Android Kapitel 6 Klassen und Vererbung

Art

Klassen werden in Kotlin mit dem Schlüsselwort class deklariert:

class Invoice {
}

Eine Klassendeklaration umfasst einen Klassennamen, einen Klassenheader (Parametertypen, Konstruktoren usw.) und einen Klassenkörper (Inhalt in geschweiften Klammern). Sowohl der Klassenkopf als auch der Klassenkörper sind optional; wenn eine Klasse keinen Klassenkörper hat, können die geschweiften Klammern weggelassen werden.

class Empty

Konstrukteur

In Kotlin kann eine Klasse einen primären Konstruktor und mehrere sekundäre Konstruktoren haben. Der primäre Konstruktor ist Teil des Klassenheaders, wird nach dem Klassennamen platziert und verfügt über optionale Typparameter.

class Person constructor(firstName: String) {
}

Wenn der primäre Konstruktor keine Anmerkungen oder sichtbaren Modifikatoren hat, kann sein Schlüsselwort-Konstruktor weggelassen werden.

class Person(firstName: String) {
}

Der Hauptkonstruktor darf keine Codeanweisungen enthalten und der Initialisierungscode kann im mit dem Schlüsselwort init deklarierten Initialisierungsblock platziert werden:

class Customer(name: String) {
    init {
        logger.info("Customer initialized with value ${name}")
    }
}

Hinweis: Die Parameter im Hauptkonstruktor können im Initialisierungsblock und auch bei der Initialisierung von Eigenschaften im Klassenkörper verwendet werden.

class Customer(name: String) {
    val customerKey = name.toUpperCase()
}

Im Allgemeinen können wir Eigenschaften im Hauptkonstruktor deklarieren und initialisieren:

class Person(val firstName: String, val lastName: String, var age: Int) {
    // ...
}

Wenn der Konstruktor über Anmerkungen oder sichtbare Modifikatoren verfügt, kann das Schlüsselwort „constructor“ nicht weggelassen werden und die Modifikatoren müssen vor dem Konstruktor platziert werden.

class Customer public @Inject constructor(name: String) { ... }

sekundärer Konstruktor

Klassen können den Konstruktor auch verwenden, um sekundäre Konstruktoren zu deklarieren.

class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    }
}

Wenn eine Klasse über einen primären Konstruktor verfügt, muss jeder sekundäre Konstruktor entweder an den primären Konstruktor oder an einen anderen sekundären Konstruktor delegieren. Delegieren Sie innerhalb derselben Klasse mit dem Schlüsselwort this an einen Konstruktor.

class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

Wenn eine nicht abstrakte Klasse keinen Konstruktor hat, generiert das System automatisch einen primären Konstruktor ohne Parameter und dieser ist öffentlich. Wenn Sie nicht möchten, dass die Klasse über einen öffentlichen Konstruktor verfügt, müssen Sie einen Konstruktor ohne Argumente deklarieren, anstatt den Systemstandard zu verwenden.

class DontCreateMe private constructor () {
}

Hinweis : Wenn in der JVM ein primärer Konstruktor Standardwerte für alle Parameter hat, erstellt der Compiler automatisch einen Konstruktor ohne Argumente mit diesen Werten. Auf diese Weise können einige Bibliotheken von Drittanbietern wie JackJson oder JPA problemlos über den Konstruktor ohne Argumente instanziiert werden.

fun main(args: Array<String>) {
    var customer = Customer()
    println(customer.customerName) // admin
    // var student = Student() 
    // 由于 age 没有初始化,自动没有自动创建无参构造函数,编译器报错
}

class Customer(val customerName: String = "admin")

class Student(val name: String = "HanMeimei" , val age: Int)

Erstellen Sie eine Instanz der Klasse

Normalerweise können wir den Konstruktor aufrufen, um eine Instanz einer Klasse zu erstellen:

val invoice = Invoice()

val customer = Customer("Joe Smith")

Hinweis : In Kotlin gibt es kein neues Schlüsselwort.

Klassenmitglieder

Eine Klasse besteht normalerweise aus den folgenden Teilen:
- Konstruktor und Initialisierungsblock
- Funktion
- Attribut
- verschachtelte Klasse und innere Klasse
- Objektdeklaration

erben

Alle Klassen in Kotlin erben standardmäßig von Any, und Any ist standardmäßig eine Oberklasse, die keine übergeordnete Klasse hat. Any ist nicht java.lang.Object; Hinweis: Any hat keine Funktionen außer equal(), hashCode() und toString().

Wir können die Vererbungsbeziehung durch einen Doppelpunkt gefolgt von der übergeordneten Klasse im Klassenheader deklarieren:

open class Base(p: Int)

class Derived(p: Int) : Base(p)

Wenn eine Klasse einen primären Konstruktor hat, muss ihre übergeordnete Klasse bei der Vererbung initialisiert werden, wie im obigen Code.

Wenn eine Klasse keinen primären Konstruktor hat, muss jeder sekundäre Konstruktor entweder die übergeordnete Klasse mit dem Schlüsselwort super initialisieren oder an einen anderen Konstruktor delegieren, der die übergeordnete Klasse initialisiert hat. Darüber hinaus können verschiedene sekundäre Konstruktoren unterschiedliche Konstruktoren in der übergeordneten Klasse aufrufen.

class MyView : View {
    constructor(ctx: Context) : super(ctx)

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}

Das Schlüsselwort open ist das Gegenteil des Schlüsselworts final in Java: Es ermöglicht anderen Klassen, von dieser Klasse zu erben. Alle Klassen in Kotlin sind standardmäßig final.

Override-Funktion

Im Gegensatz zu Java müssen überschreibende Funktionen in Kotlin explizit deklariert werden:

open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
    override fun v() {}
    // fun nv(){} // 不用关键字 override 声明,编辑器会报错
    // override fun nv(){} // 父类中函数不声明为 open ,编译器也报错
}

Eine Überschreibungsfunktion ist standardmäßig geöffnet und kann von Unterklassen überschrieben werden. Wenn Sie nicht möchten, dass sie von Unterklassen überschrieben wird, können Sie die endgültige Änderung verwenden:

open class AnotherDerived() : Base() {
    final override fun v() {}
}

Override-Attribut

Die Methode zum Überschreiben von Eigenschaften ähnelt der Methode zum Überschreiben von Funktionen. Wenn in der Unterklasse Eigenschaften mit demselben Namen wie in der übergeordneten Klasse vorhanden sind, müssen die Eigenschaften in der Unterklasse durch Überschreiben geändert werden, und die Eigenschaftstypen sind kompatibel.

open class Foo {
    open val x: Int get { ... }
}

class Bar1 : Foo() {
    override val x: Int = ...
}

Es kann durch die Initialisierung wie oben oder durch Verwendung einer Getter-Funktion überschrieben werden:

open class A{
    open val x:Int = 0
}

class B : A(){
    override val x: Int
        get() = TODO("not implemented")
}

Wenn es vom Typ var ist und beim Überschreiben nicht initialisiert wird, müssen sowohl Getter als auch Setter Folgendes haben:

open class A{
    open var x:Int = 0
}

class B : A(){
    override var x: Int
        get() = TODO("not implemented")
        set(value){...}
}

Sie können eine Eigenschaft vom Typ val auch mit einer Eigenschaft vom Typ var überschreiben, jedoch nicht umgekehrt. Da eine Eigenschaft vom Typ val im Wesentlichen eine Getter-Funktion deklariert und durch das Überschreiben mit var lediglich eine zusätzliche Setter-Funktion in der Unterklasse hinzugefügt wird. Darüber hinaus können Sie auch Eigenschaften im Hauptkonstruktor überschreiben:

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
}

Hinweis : Schnittstellen und Mitglieder von Schnittstellen sind standardmäßig geöffnet.

Regeln außer Kraft setzen

Wenn eine Klasse und ihre unmittelbare Elternklasse Mitglieder mit demselben Namen haben, müssen diese Mitglieder überschrieben werden; außerdem können wir in Unterklassen mit super bestimmen, welches Mitglied welcher Elternklasse (Elternschnittstelle) aufgerufen wird.

open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}

interface B {
    fun f() { print("B") } 
    fun b() { print("b") }
}

class C() : A(), B {
    override fun f() {
        super<A>.f() // A.f()
        super<B>.f() // B.f()
    }
}

abstrakte Klasse

Eine Klasse kann mit abstract als abstrakt deklariert werden. Mitglieder einer abstrakten Klasse müssen nicht in sich selbst implementiert werden. Darüber hinaus müssen wir die abstrakte Klasse und ihre Mitglieder nicht als offen deklarieren, da diese auch vererbt werden können.

Wir können auch eine nicht abstrakte Funktion einer nicht abstrakten Klasse mit einer abstrakten Funktion einer abstrakten Klasse überschreiben:

open class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()
}

Begleitobjekt

Im Gegensatz zu Java oder C# verfügen Klassen in Kotlin nicht über statische Methoden. In den meisten Fällen können stattdessen Funktionen auf Paketebene verwendet werden. Wenn Sie eine Funktion deklarieren müssen, die ohne Klasseninstanziierung aufgerufen werden kann und auf die interne Struktur dieser Klasse zugreifen kann, können Sie in dieser Klasse ein Objekt deklarieren. Wenn Sie in der Klasse ein Begleitobjekt deklarieren, können Sie die Funktion dieses Objekts genauso aufrufen wie eine statische Methode in Java/C#.

Guess you like

Origin blog.csdn.net/niuzhucedenglu/article/details/72866581