Menu
Coddy logo textTech

super et constructeurs

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

super.method() appelle la version de la superclasse d'une méthode depuis l'intérieur d'une redéfinition. Une sous-classe peut étendre le comportement hérité au lieu de le remplacer :

open class Notification(val text: String) {
    open fun render() = "[info] $text"
}
class Reminder(text: String, val minutes: Int) : Notification(text) {
    override fun render() = super.render() + " (in $minutes min)"
}

À l'intérieur de main :

println(Notification("backup done").render())
println(Reminder("meeting", 10).render())

Résultat :

[info] backup done
[info] meeting (in 10 min)

Chaque sous-classe doit appeler un constructeur de classe parente. Avec un constructeur primaire, l'appel fait partie de l'en-tête, : Base(arguments), et les arguments peuvent être calculés à partir des paramètres de la sous-classe :

open class Product(val name: String, val price: Int)

class Discounted(name: String, price: Int, val percent: Int) :
    Product(name, price * (100 - percent) / 100)

À l'intérieur de main :

val tea = Discounted("tea", 500, 10)
println("${tea.name} ${tea.price} (${tea.percent}% off)")

Sortie :

tea 450 (10% off)

La création s’effectue du haut vers le bas de la hiérarchie : les initialiseurs de propriétés et les blocs init de la superclasse s’exécutent d’abord, puis ceux de la sous-classe :

open class Base(name: String) {
    init { println("Base init for $name") }
}
class Child(name: String) : Base(name.uppercase()) {
    init { println("Child init for $name") }
}

À l’intérieur de main :

Child("kit")

Sortie :

Base init for KIT
Child init for kit

Une classe sans constructeur primaire appelle la superclasse depuis chaque constructeur secondaire avec super(...), ou délègue à l’un de ses propres constructeurs avec this(...) :

open class Shape(val name: String)

class Rect : Shape {
    val w: Int
    val h: Int

    constructor(w: Int, h: Int) : super("rect") {
        this.w = w
        this.h = h
    }

    constructor(side: Int) : this(side, side)
}

Dans main :

val r = Rect(3)
println("${r.name} ${r.w}x${r.h}")

Sortie :

rect 3x3

Comme la superclasse est initialisée en premier, elle ne doit pas appeler les membres open depuis son constructeur ou son init. La redéfinition s'exécute avant que les propres propriétés de la sous-classe aient reçu leurs valeurs :

open class Base {
    init { println("Base sees: ${describe()}") }
    open fun describe() = "base"
}
class Child : Base() {
    val label = "child"
    override fun describe() = "label is $label"
}

Dans main :

Child()

Sortie :

Base sees: label is null
challenge icon

Défi

Facile

Notification(text) possède une méthode ouverte render() qui renvoie [info] text. Complétez les sous-classes : le render() de Warning renvoie [warn] TEXT avec le texte en majuscules, et Reminder, qui stocke également minutes, renvoie le résultat de la superclasse suivi de (in 10 min), en utilisant super.

Le code fourni lit des lignes info,text, warn,text ou remind,text,10, construit l'objet correspondant dans une seule List<Notification> et affiche render() pour chacun.

Votre code doit se trouver dans Notification.kt, Warning.kt et Reminder.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 notes = mutableListOf<Notification>()
    for (line in input) {
        val p = line.split(",")
        notes.add(when (p[0]) {
            "warn" -> Warning(p[1])
            "remind" -> Reminder(p[1], p[2].toInt())
            else -> Notification(p[1])
        })
    }
    for (n in notes) println(n.render())
}
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