Menu
Coddy logo textTech

Redéfinition des membres

Fait partie de la section Programmation orientée objet du Journey Kotlin de Coddy. Leçon 18 sur 57.

Une sous-classe peut remplacer une méthode héritée par sa propre version. La superclasse marque la méthode avec open, et la sous-classe la déclare à nouveau avec 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"
}

À l’intérieur de main :

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

Sortie :

Woof
Meow
...

La version qui s’exécute est choisie par la classe réelle de l’objet, même lorsque le type de la variable est la superclasse. Le code à l’intérieur de la superclasse qui appelle une méthode ouverte obtient également la version de la sous-classe :

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

À l’intérieur de main :

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

Sortie :

Rex says Woof
Generic says ...

Les propriétés peuvent être redéfinies de la même manière : open val dans la superclasse, override val dans la sous-classe, soit comme propriété normale, propriété de constructeur ou accesseur calculé :

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"
}

À l'intérieur de main :

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

Sortie :

shape: 0
triangle: 3
6-gon: 6

Un membre marqué override est de nouveau ouvert, de sorte qu’une sous-classe de la sous-classe peut encore le remplacer une fois ; final override l’en empêche. Un membre sans open ne peut pas du tout être remplacé, et une sous-classe ne peut pas déclarer de membre ayant la même signature :

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"   // erreur : 'sound' dans 'Dog' est final
    // fun sleep() = "nap"            // erreur : 'sleep' masque un membre de la superclasse
}
challenge icon

Défi

Facile

Animal possède legs() (4), sound() (...) et describe(), qui renvoie Rex has 4 legs and says Woof, construit à partir de legs() et sound(). Rendez legs() et sound() surchargeables et complétez les sous-classes en ne surchargeant que ces deux méthodes : Dog dit Woof, Bird a 2 pattes et dit Tweet, et Snake a 0 patte et dit Hiss. describe() reste tel quel dans Animal.

Le code fourni lit les lignes dog,Rex, bird,Pip, snake,Kaa ou tout autre type (un simple Animal), stocke les animaux dans une seule List<Animal> et affiche describe() pour chacun.

Votre code va dans Animal.kt, Dog.kt, Bird.kt et Snake.kt. Main.kt contient le code d'entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

fun main() {
    // Code d'entrée/sortie fourni : le garder tel quel
    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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Playground Kotlin