Sobes.tech
Junior

Comment l'héritage et le polymorphisme sont-ils organisés en Kotlin?

sobes.tech IA

Réponse de l'IA

En Kotlin, l'héritage est réalisé via des mécanismes de classes et d'interfaces. Les classes peuvent hériter d'une seule autre classe (héritage simple), mais peuvent implémenter plusieurs interfaces.

Par défaut, toutes les classes en Kotlin sont 'final', c'est-à-dire qu'elles ne peuvent pas être héritées. Pour autoriser l'héritage, une classe doit être explicitement marquée avec le mot-clé open.

Héritage de classes :

open class Shape { // Classe de base, marquée comme open
    open fun draw() { // Méthode pouvant être redéfinie
        println("Dessiner une forme")
    }
}

class Circle : Shape() { // Héritage de Shape
    override fun draw() { // Redéfinition de la méthode
        println("Dessiner un cercle")
    }
}

Dans le constructeur de la classe fille, il est nécessaire d'appeler explicitement ou implicitement le constructeur de la classe de base.

Interfaces :

Les interfaces en Kotlin sont similaires à celles de Java 8 et peuvent contenir des méthodes abstraites et des méthodes avec une implémentation. Les classes peuvent implémenter une ou plusieurs interfaces.

interface Drawable {
    fun draw() // Méthode abstraite
    fun description() { // Méthode avec une implémentation par défaut
        println("Ceci est un objet dessinable")
    }
}

class Square : Drawable {
    override fun draw() { // Implémentation de la méthode abstraite
        println("Dessiner un carré")
    }
    // description() peut être redéfini, mais ce n'est pas obligatoire
}

Polymorphisme :

Le polymorphisme en Kotlin est réalisé grâce à la capacité de travailler avec des objets de différentes classes via un type de base commun (classe ou interface). Cela permet d'appeler des méthodes spécifiques au type réel de l'objet lors de l'exécution.

fun render(drawable: Drawable) {
    drawable.draw() // Appel de la méthode draw() selon le type réel de l'objet
    drawable.description()
}

fun main() {
    val circle: Shape = Circle() // L'objet Circle est considéré comme Shape
    circle.draw() // Appel de draw() de Circle grâce au polymorphisme

    val square: Drawable = Square() // L'objet Square est considéré comme Drawable
    render(square) // Appel de draw() et description() de Square
}

Dans cet exemple, render fonctionne avec tout objet implémentant Drawable. L'appel à drawable.draw() exécutera l'implémentation de la méthode draw pour le type spécifique de l'objet (Square dans ce cas).

Différences entre héritage de classes et implémentation d'interfaces :

  • Héritage de classe : Établit une relation "est un" (is-a). La classe fille hérite de l'état et du comportement de la classe de base.
  • Implémentation d'interface : Définit une "capacité" ou un "contrat". La classe promet de fournir l'implémentation de toutes les méthodes abstraites de l'interface.

Tableau comparatif :

Caractéristique Héritage de classe Implémentation d'interface
Type de relation est-a Capacité / Contrat
Multiplicité Unique Multiple
État Hérite de l'état de la classe de base N'hérite pas de l'état
Implémentation des méthodes Peut contenir une implémentation Peut contenir une implémentation par défaut (depuis Java 8)