ProgrammationDéveloppeur Backend

Qu'est-ce qu'une interface scellée en Kotlin, comment cela fonctionne-t-il et à quoi cela sert-il ? Décrivez les particularités d'utilisation, les limitations et fournissez un exemple.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question :

Les interfaces avec le modificateur sealed sont apparues en Kotlin comme une évolution du concept de sealed class. Avant Kotlin 1.5, seules les classes scellées permettaient de limiter l'ensemble des héritiers possibles, ce qui est particulièrement important pour un travail sécuritaire avec des hiérarchies d'états (machines à états, DSL, etc.). En introduisant les interfaces scellées, les développeurs ont permis de limiter de manière similaire les implémentations des interfaces, sans être liés aux classes.

Problème :

Une interface ouverte simple peut être implémentée n'importe où dans le programme, ce qui peut entraîner une croissance incontrôlée du nombre d'implémentations et compliquer la maintenance du code. Lors du traitement via une expression when, le compilateur ne peut pas avertir des branches non prises en compte.

Solution :

L'interface sealed limite les implémentations uniquement à celles définies dans un seul module (ou le même fichier, si l'interface n'est pas de niveau supérieur). Ce type de contrôle est appliqué pour des structures sécurisées de type enum, le pattern ADT et les gestionnaires d'état. Le compilateur connaît toutes les implémentations et aide à l'analyse du code.

Exemple de code :

sealed interface NetworkResult class Success(val data: String): NetworkResult class Error(val cause: Throwable): NetworkResult object Loading: NetworkResult fun handleResult(result: NetworkResult): String = when (result) { is Success -> "Success with ${result.data}" is Error -> "Error: ${result.cause.message}" Loading -> "Loading..." }

Caractéristiques clés :

  • Les interfaces scellées assurent une limitation du nombre d'implémentations pour améliorer la sécurité des types.
  • Elles fonctionnent avec l'expression when : le compilateur vérifie l'exhaustivité.
  • Les implémentations peuvent être des classes, ainsi que des objets et d'autres types scellés, mais uniquement dans le cadre d'un module unique.

Questions pièges.

Peut-on implémenter une interface scellée en dehors du fichier actuel ?

Réponse : Contrairement aux classes scellées, les interfaces scellées peuvent être implémentées dans d'autres fichiers, mais uniquement dans le cadre du module actuel (ou de l'unité de compilation, si l'interface n'est pas de niveau supérieur).

Les interfaces scellées peuvent-elles avoir des méthodes ouvertes avec des implémentations par défaut ?

Oui, comme les interfaces normales, une interface scellée peut contenir des implémentations par défaut de fonctions.

sealed interface Mode { fun description(): String = "Unknown mode" }

Est-il possible de sérialiser une interface scellée à l'aide de sérialiseurs standard (par exemple, kotlinx.serialization) ?

C'est possible, mais il sera nécessaire de spécifier explicitement toutes les implémentations. Dans Kotlinx.serialization, le support des interfaces scellées n'a pas été immédiat, il est donc important de préciser les types sérialisables.

Erreurs typiques et anti-patterns

  • Définir des implémentations en dehors du module
  • Utilisation excessive des interfaces scellées au lieu d'énums, lorsque les options sont moins nombreuses et que la structure est plus simple
  • Ne pas effectuer de contrôle d'exhaustivité lors de la mise à jour d'une interface scellée

Exemple de la vie réelle

Cas négatif

Dans le projet, une interface scellée a été décrite pour tous les types d'états UI, et les implémentations ont commencé à apparaître dans différentes parties de l'application. Ensuite, un nouveau type d'état a été ajouté, et le bloc de traitement n'a pas été mis à jour, ce qui a conduit à l'ignorance du nouvel état dans les logs.

Avantages :

  • Ajout rapide de nouveaux états

Inconvénients :

  • La sécurité des types diminue, des branches de logique non prises en compte apparaissent

Cas positif

Une interface scellée a été utilisée pour toutes les réponses réseau. Grâce à cela, lors de l'ajout d'un nouveau type de réponse, l'IDE a immédiatement mis en surbrillance tous les endroits où le traitement est commuté via when. L'erreur est corrigée immédiatement, il n'y a pas de trous inattendus dans la logique.

Avantages :

  • Refactoring sécurisé
  • Impossible d'oublier un nouveau type d'état

Inconvénients :

  • Dans de grandes structures, la limitation du nombre d'options peut entraîner une augmentation de la charge de maintenance