JetBrains teste dans Kotlin 2.5.0 deux nouveaux mécanismes nommés Companion Blocks et Companion Extensions, afin d’étendre la manière de définir les membres associés à un type et d’améliorer l’interopérabilité entre les différentes plateformes Kotlin. L’entreprise affirme que le nouveau design ouvre des modèles de programmation qui n’étaient pas facilement accessibles avec les Companion Objects traditionnels.
Qu’ajoute le nouveau mécanisme ?
Les membres associés à un type servent à définir des constantes, des utilitaires et des fonctions de construction qui n’appartiennent pas à un objet individuel, comme une constante représentant le vecteur nul ou une fonction qui crée un vecteur selon un angle donné. Auparavant, cet usage reposait sur les Companion Objects, tandis que les nouveaux blocs companion permettent d’écrire ce type de membres dans une syntaxe plus proche de leur définition au sein du type lui-même.
Les Companion Extensions permettent quant à elles d’ajouter des membres associés à n’importe quelle classe ou interface, même lorsque le développeur ne possède pas le code d’origine, et même si le type provient de Java ou ne contient pas à l’origine de Companion Object. Il devient ainsi possible d’étendre des types externes sans modifier leur définition de base.
Modifications de la compilation et de la compatibilité
Le nouveau mécanisme diffère des Companion Objects par sa stratégie de compilation. Sur la plateforme JVM, les Companion Blocks sont compilés en membres static, ce qui rapproche leur comportement de celui des membres statiques sur d’autres plateformes. JetBrains estime que cela pourrait être utile à Kotlin Multiplatform, puisqu’il serait possible de définir des membres attendus dans un bloc companion, puis de les réaliser à l’aide d’une classe Java contenant des membres static.
Ces fonctionnalités restent toutefois expérimentales. L’activation des Companion Blocks nécessite l’option -Xcompanion-blocks, tandis que l’utilisation combinée des blocs et des extensions nécessite l’option -Xcompanion-blocks-and-extensions.
Limites de l’utilisation expérimentale
Lors de l’utilisation des Companion Extensions, le compilateur produit des fichiers binaires de préversion. En conséquence, les autres projets ou bibliothèques pourraient ne pas être en mesure de consommer comme dépendances des bibliothèques utilisant ces extensions tant que la fonctionnalité ne sera pas officiellement stabilisée. La même limitation ne s’applique pas à l’exposition des Companion Blocks, mais leurs utilisateurs devront également activer la fonctionnalité.
Faut-il migrer les Companion Objects ?
JetBrains ne recommande pas une migration immédiate. Les Companion Objects restent une composante essentielle de Kotlin et leur prise en charge complète est garantie. Les Companion Blocks pourraient être l’option privilégiée pour le nouveau code dans la plupart des cas, mais les Companion Objects restent nécessaires dans certaines situations, notamment lorsque le companion doit implémenter une interface, puisqu’ils sont compilés en une classe complète.
En pratique, il peut suffire dans de nombreux cas de supprimer le mot object pour passer à un Companion Block, mais le projet et tout le code qui en dépend devront être recompilés. JetBrains avertit également que certains outils de l’écosystème ne sont peut-être pas encore prêts à gérer la nouvelle syntaxe.
Pourquoi cette évolution est-elle importante ?
Ce changement est important pour les développeurs Kotlin Multiplatform et les auteurs de bibliothèques, car il tente de réduire l’écart entre le concept de membres statiques sur la JVM et sur les autres plateformes. Toutefois, sa valeur pratique reste actuellement liée à une phase expérimentale et à la rapidité avec laquelle les outils de build, les bibliothèques et les éditeurs seront mis à jour. Les Companion Blocks semblent donc adaptés à l’expérimentation et à l’évaluation du design, mais pas à une migration étendue et sûre avant la stabilisation de la fonctionnalité.