Menu
Coddy logo textTech

Überschreiben von Membern

Teil des Abschnitts Objektorientierte Programmierung der Kotlin-Journey von Coddy. Lektion 18 von 57.

Eine Unterklasse kann eine geerbte Methode durch ihre eigene Version ersetzen. Die Oberklasse markiert die Methode mit open, und die Unterklasse deklariert sie erneut mit override:

open class Animal(val name: String) {
    open fun sound() = "..."
}
class Dog(name: String) : Animal(name) {
    override fun sound() = "Woof"
}
class Cat(name: String) : Animal(name) {
    override fun sound() = "Meow"
}

Innerhalb von main:

println(Dog("Rex").sound())
println(Cat("Tom").sound())
println(Animal("Generic").sound())

Ausgabe:

Woof
Meow
...

Die ausgeführte Version wird von der tatsächlichen Klasse des Objekts ausgewählt, selbst wenn der Typ der Variable die Oberklasse ist. Auch Code innerhalb der Oberklasse, der eine offene Methode aufruft, erhält die Version der Unterklasse:

open class Animal(val name: String) {
    open fun sound() = "..."
    fun speak() = "$name says ${sound()}"
}
class Dog(name: String) : Animal(name) {
    override fun sound() = "Woof"
}

Innerhalb von main:

val pets: List<Animal> = listOf(Dog("Rex"), Animal("Generic"))
for (p in pets) println(p.speak())

Ausgabe:

Rex says Woof
Generic says ...

Eigenschaften können auf dieselbe Weise überschrieben werden: open val in der Oberklasse, override val in der Unterklasse, entweder als normale Eigenschaft, als Konstruktor-Eigenschaft oder als berechneter Getter:

open class Shape {
    open val name = "shape"
    open val corners = 0
}
class Triangle : Shape() {
    override val name = "triangle"
    override val corners = 3
}
class Polygon(override val corners: Int) : Shape() {
    override val name: String
        get() = "$corners-gon"
}

Innerhalb von main:

for (s in listOf(Shape(), Triangle(), Polygon(6))) println("${s.name}: ${s.corners}")

Ausgabe:

shape: 0
triangle: 3
6-gon: 6

Ein als override markiertes Element ist wieder offen, sodass eine Unterklasse der Unterklasse es erneut überschreiben kann; final override verhindert dies. Ein Element ohne open kann überhaupt nicht überschrieben werden, und eine Unterklasse darf kein Element mit derselben Signatur deklarieren:

open class Animal {
    open fun sound() = "..."
    fun sleep() = "zzz"
}
open class Dog : Animal() {
    final override fun sound() = "Woof"
}
class Puppy : Dog() {
    // override fun sound() = "Yip"   // Fehler: 'sound' in 'Dog' ist final
    // fun sleep() = "nap"            // Fehler: 'sleep' versteckt ein Mitglied der Superklasse
}
challenge icon

Aufgabe

Einfach

Animal verfügt über legs() (4), sound() (...) und describe(), das Rex has 4 legs and says Woof zurückgibt und aus legs() und sound() erstellt wird. Mache legs() und sound() überschreibbar und vervollständige die Unterklassen, indem du nur diese beiden Methoden überschreibst: Dog sagt Woof, Bird hat 2 Beine und sagt Tweet, und Snake hat 0 Beine und sagt Hiss. describe() bleibt so, wie es in Animal ist.

Der bereitgestellte Code liest Zeilen wie dog,Rex, bird,Pip, snake,Kaa oder eine andere Art (ein einfaches Animal), speichert die Tiere in einer List<Animal> und gibt für jedes describe() aus.

Dein Code gehört in Animal.kt, Dog.kt, Bird.kt und Snake.kt. Main.kt enthält den bereitgestellten Eingabe-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

fun main() {
    // Gelieferter Ein-/Ausgabecode: belasse ihn wie er ist
    val input = generateSequence(::readLine).toList()
    val animals = mutableListOf<Animal>()
    for (line in input) {
        val (kind, name) = line.split(",")
        animals.add(when (kind) {
            "dog" -> Dog(name)
            "bird" -> Bird(name)
            "snake" -> Snake(name)
            else -> Animal(name)
        })
    }
    for (a in animals) println(a.describe())
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Kotlin-Playground