Sobes.tech
Junior

Wie sind Vererbung und Polymorphismus in Kotlin organisiert?

sobes.tech KI

Antwort von AI

In Kotlin wird Vererbung durch Klassen- und Schnittstellenmechanismen realisiert. Klassen können nur von einer anderen Klasse erben (einfache Vererbung), aber mehrere Schnittstellen implementieren.

Standardmäßig sind alle Klassen in Kotlin 'final', das heißt, sie können nicht vererbt werden. Um Vererbung zu erlauben, muss eine Klasse explizit mit dem Schlüsselwort open gekennzeichnet werden.

Klassenvererbung:

open class Shape { // Basisklasse, als open gekennzeichnet
    open fun draw() { // Methode, die überschrieben werden kann
        println("Zeichne eine Form")
    }
}

class Circle : Shape() { // Erbt von Shape
    override fun draw() { // Überschreibt die Methode
        println("Zeichne einen Kreis")
    }
}

Im Konstruktor der Kindklasse muss der Konstruktor der Basisklasse explizit oder implizit aufgerufen werden.

Schnittstellen:

Schnittstellen in Kotlin ähneln denen in Java 8 und können abstrakte Methoden sowie Methoden mit Standardimplementierung enthalten. Klassen können eine oder mehrere Schnittstellen implementieren.

interface Drawable {
    fun draw() // Abstrakte Methode
    fun description() { // Methode mit Standardimplementierung
        println("Dies ist ein zeichnungsfähiges Objekt")
    }
}

class Square : Drawable {
    override fun draw() { // Implementierung der abstrakten Methode
        println("Zeichne ein Quadrat")
    }
    // description() kann überschrieben werden, ist aber nicht erforderlich
}

Polymorphismus:

Polymorphismus in Kotlin wird durch die Fähigkeit erreicht, mit Objekten verschiedener Klassen über einen gemeinsamen Basistyp (Klasse oder Schnittstelle) zu arbeiten. Dadurch können Methoden aufgerufen werden, die spezifisch für den tatsächlichen Objekttyp sind, zur Laufzeit.

fun render(drawable: Drawable) {
    drawable.draw() // Ruft die draw() Methode je nach tatsächlichem Objekttyp auf
    drawable.description()
}

fun main() {
    val circle: Shape = Circle() // Objekt Circle wird als Shape behandelt
    circle.draw() // Ruft die draw() von Circle aufgrund des Polymorphismus auf

    val square: Drawable = Square() // Objekt Square wird als Drawable behandelt
    render(square) // Ruft draw() und description() von Square auf
}

In diesem Beispiel arbeitet render mit jedem Objekt, das Drawable implementiert. Der Aufruf drawable.draw() führt die Implementierung der Methode draw für den konkreten Objekttyp aus (Square in diesem Fall).

Unterschiede zwischen Klassenvererbung und Schnittstellenimplementierung:

  • Klassenvererbung: Stellt eine "ist-ein"-Beziehung her (is-a). Die Kindklasse erbt Zustand und Verhalten der Basisklasse.
  • Schnittstellenimplementierung: Definiert eine "Fähigkeit" oder einen "Vertrag". Die Klasse verspricht, die Implementierung aller abstrakten Methoden der Schnittstelle bereitzustellen.

Vergleichstabelle:

Eigenschaft Klassenvererbung Schnittstellenimplementierung
Beziehungstyp ist-ein (is-a) Fähigkeit / Vertrag
Mehrfachvererbung Einzelvererbung Mehrfachvererbung
Zustand Erbt Zustand der Basisklasse Erbt keinen Zustand
Methodenimplementierung Kann Implementierung enthalten Kann Standardimplementierung haben (ab Java 8)