Data class en Kotlin : pourquoi on ne peut pas les hériter et comment contourner

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Data class en Kotlin : pourquoi on ne peut pas les hériter et comment contourner (analyse sous le capot)

\n\n

Avez-vous déjà écrit data class User(val name: String), puis voulu faire data class Admin extends User ? Et obtenu une erreur rouge du compilateur ? Si oui, vous n'êtes pas seul. La question « Extend data class in Kotlin » fait partie des plus populaires sur Stack Overflow (plus de 50 000 vues).

\n\n

Aujourd'hui, nous ne nous contenterons pas de donner une réponse toute faite. Nous allons regarder sous le capot de Kotlin, comprendre pourquoi les créateurs du langage ont imposé cette limitation « sévère », et vous montrer 3 méthodes légales pour la contourner sans casser l'architecture.

\n\n

Cet article est rédigé pour le portail éducatif PythonLib — ici, nous aimons creuser en profondeur, pas simplement copier des extraits de code.

\n\n

Pourquoi une data class ne peut-elle pas être héritée ? Regardons dans le bytecode

\n\n

Allons droit au but. Écrivons une simple data class et voyons ce que le compilateur génère :

\n\n
data class User(val name: String, val age: Int)
\n\n

Sous le capot, Kotlin crée :

\n
    \n
  • equals() — compare tous les champs
  • \n
  • hashCode() — un hash basé sur tous les champs
  • \n
  • toString() — une représentation textuelle soignée
  • \n
  • copy() — une fonction de copie avec modification des champs
  • \n
  • componentN() — la déstructuration
  • \n
\n\n

Imaginez maintenant que vous héritez d'une data class :

\n\n
open data class Base(val x: Int)\ndata class Derived(val x: Int, val y: Int) : Base(x) // Erreur de compilation !
\n\n

Kotlin affiche : « Inheritance of data classes is not allowed ». Pourquoi ? Analysons cela.

\n\n

Problème n°1 : copy() est cassée. La fonction copy() est générée uniquement pour les champs de la classe courante. Si vous avez Derived héritée de Base, alors copy() dans Base ne connaît pas le champ y. En appelant base.copy(), vous perdrez les données de l'héritière.

\n\n

Problème n°2 : equals() et hashCode(). Imaginez : Base(1) et Derived(1, 2). Doivent-ils être égaux ? Si oui, la symétrie est violée (car Derived contient plus de champs). Si non, le contrat equals/hashCode est violé. Kotlin a choisi la voie sûre : interdire l'héritage.

\n\n

Problème n°3 : componentN(). val (x) = base et val (x, y) = derived — des nombres de composants différents. L'héritage créerait de la confusion.

\n\n

Conclusion : la data class est conçue pour des conteneurs de données immuables, pas pour des hiérarchies. C'est une décision de conception délibérée du langage.

\n\n

Méthode n°1 : La composition plutôt que l'héritage (recommandée)

\n\n

La méthode la plus propre est de ne pas hériter, mais d'inclure une data class dans une autre. Cela s'appelle la composition.

\n\n
data class Address(val city: String, val street: String)\n\ndata class User(\n    val name: String,\n    val age: Int,\n    val address: Address // composition\n)\n\nfun main() {\n    val address = Address("Moscou", "Tverskaïa")\n    val user = User("Anna", 25, address)\n    println(user) // User(name=Anna, age=25, address=Address(city=Moscou, street=Tverskaïa))\n    \n    // La copie fonctionne parfaitement\n    val user2 = user.copy(age = 26)\n    println(user2) // User(name=Anna, age=26, address=Address(city=Moscou, street=Tverskaïa))\n}\n
\n\n

Avantages : tout fonctionne « prêt à l'emploi », pas de surprises avec equals/hashCode, code transparent.

\n\n

Inconvénients : si vous avez besoin de nombreux niveaux d'imbrication, vous obtenez une « poupée russe ». Mais cela se résout par la normalisation des données.

\n\n

Méthode n°2 : Sealed class + data class (pour les hiérarchies strictes)

\n\n

Si vous avez vraiment besoin d'une hiérarchie (par exemple, différents types d'utilisateurs), utilisez une sealed class (ou sea

Blogs

Book Recommendations