Cours scellés à Kotlin

1. Introduction

En termes simples, le langage Kotlin a emprunté un certain nombre de concepts à d'autres langages fonctionnels pour aider à écrire un code plus sûr et plus lisible. Les hiérarchies scellées sont l'un de ces concepts.

2. Qu'est-ce qu'une classe scellée?

Les classes scellées nous permettent de corriger les hiérarchies de types et interdisent aux développeurs de créer de nouvelles sous-classes.

Ils sont utiles lorsque vous avez une hiérarchie d'héritage très stricte, avec un ensemble spécifique de sous-classes possibles et pas d'autres. Le compilateur garantit que seules les classes définies dans le même fichier source que la classe scellée peuvent en hériter.

Les classes scellées sont également implicitement abstraites . Ils doivent être traités comme tels dans le reste de votre code, sauf que rien d'autre ne peut les implémenter.

Les classes scellées peuvent avoir des champs et des méthodes qui y sont définis, y compris des fonctions abstraites et implémentées. Cela signifie que vous pouvez avoir une représentation de base de la classe, puis l'ajuster en fonction des sous-classes.

3. Quand utiliser les classes scellées?

Les classes scellées sont conçues pour être utilisées lorsqu'il existe un ensemble très spécifique d'options possibles pour une valeur, et où chacune de ces options est fonctionnellement différente - uniquement des types de données algébriques.

Les cas d'utilisation courants peuvent inclure la mise en œuvre d'une machine à états ou dans la programmation monadique, qui devient de plus en plus populaire avec l'avènement des concepts de programmation fonctionnelle.

Chaque fois que vous avez plusieurs options et qu'elles ne diffèrent que par la signification des données, vous feriez peut-être mieux d'utiliser les classes Enum à la place.

Chaque fois que vous avez un nombre inconnu d'options, vous ne pouvez pas utiliser une classe scellée car cela vous empêchera d'ajouter des options en dehors du fichier source d'origine.

4. Rédaction de classes scellées

Commençons par écrire notre propre classe scellée - le bon exemple d'une telle hiérarchie scellée est un Optional de Java 8 - qui peut être Some ou None.

Lors de la mise en œuvre de cela, il est très judicieux de restreindre la possibilité de créer de nouvelles implémentations - les deux implémentations fournies sont exhaustives et personne ne doit ajouter les leurs.

En tant que tel, nous pouvons implémenter ceci:

sealed class Optional { // ... abstract fun isPresent(): Boolean } data class Some(val value: V) : Optional() { // ... override fun isPresent(): Boolean = true } class None : Optional() { // ... override fun isPresent(): Boolean = false }

Il peut maintenant être garanti que chaque fois que vous avez une instance d' Optionnel , vous avez en fait un Some ou un None.

Dans Java 8, l'implémentation réelle est différente en raison de l'absence de classes scellées.

Nous pouvons ensuite utiliser ceci dans nos calculs:

val result: Optional = divide(1, 0) println(result.isPresent()) if (result is Some) { println(result.value) }

La première ligne renverra soit un certain soit un aucun . Nous sortons ensuite si nous avons obtenu un résultat ou non.

5. Utiliser avec quand

Kotlin prend en charge l'utilisation de classes scellées dans ses constructions when . Comme il existe toujours un ensemble exact de sous-classes possibles, le compilateur est capable de vous avertir si une branche n'est pas gérée, exactement de la même manière qu'il le fait pour les énumérations.

Cela signifie que dans de telles situations, il n'y a normalement pas besoin d'un gestionnaire fourre-tout, ce qui signifie que l'ajout d'une nouvelle sous-classe est automatiquement sûr - le compilateur vous avertira immédiatement si vous ne l'avez pas géré, et vous aurez besoin pour corriger ces erreurs avant de continuer.

L'exemple ci-dessus peut être étendu pour afficher le résultat ou une erreur selon le type renvoyé:

val message = when (result) { is Some -> "Answer: ${result.value}" is None -> "No result" } println(message)

Si l'une des deux branches manquait, cela ne compilerait pas et entraînerait à la place une erreur de:

'when' expression must be exhaustive, add necessary 'else' branch

6. Résumé

Les classes scellées peuvent être un outil précieux pour votre boîte à outils de conception d'API. Autoriser une hiérarchie de classes bien connue et structurée qui ne peut être que l'une des classes attendues peut aider à supprimer tout un ensemble de conditions d'erreur potentielles de votre code, tout en facilitant la lecture et la maintenance.

Comme toujours, des extraits de code peuvent être trouvés sur GitHub.