Réification de l’effacé – Développeurs Android
Le titre peut ressembler à un Film d’horreur classé B, mais en réalité, le mot clé « réifié » de Kotlin vous aide à faire des choses qui n’étaient pas possibles auparavant. Génériques assurer la sécurité des types et vous aider à éviter les conversions de types explicites Les génériques étendent le système de type pour permettre à un type ou à une méthode de fonctionner sur des objets de différents types tout en offrant une sécurité de type à la compilation. D’un autre côté, les génériques peuvent être limitatifs lorsque vous devez accéder aux informations de type dans une fonction générique, et le compilateur vous dit que les informations n’existent pas!
Ces informations de type manquantes sont le résultat de la façon dont les génériques sont implémentés dans la JVM (allusion: effacement de type, dont nous parlerons plus loin). Pour contourner ce problème, vous pouvez accéder au type générique supprimé en passant la classe du type générique en tant que paramètre de la fonction.
Ce n’est pas trop mal, mais comme vous le savez dans d’autres articles de la série de vocabulaire Kotlin, Kotlin déteste le code passe-partout et vise à vous aider à écrire moins de code! Kotlin résout ce problème avec un mot-clé unique, réifié, qui vous permet d’accéder aux informations de type à partir d’une fonction générique. Si vous connaissez le fonctionnement des génériques, vous vous demandez peut-être comment cela est possible. Voyons comment 🙂
Avant l’ajout de génériques à Java avec la version 5.0, les informations de type n’existaient pas dans les collections. Cela signifie qu’il n’y a aucune indication si un ArrayList
est un ArrayList
de String
, Integer
ou tout autre type d’objet.
Sans génériques, chaque fois que vous souhaitez accéder à un objet d’une collection, vous devez effectuer un cast explicite. De plus, il n’y a aucune protection contre les transtypages non valides qui entraînent des exceptions d’exécution.
Pour résoudre ce problème, des génériques ont été ajoutés dans Java 5. Avec les génériques, vous pouvez définir un type spécifique pour une collection et le compilateur vous avertira si vous essayez d’ajouter un autre type. De plus, vous n’avez pas besoin d’effectuer de transtypages explicites, ce qui peut entraîner des exceptions d’exécution.
Les génériques sont implémentés avec une astuce appelée effacement de type. Puisqu’il n’y avait aucune information de type avant Java 5, le compilateur Java remplace d’abord toutes les informations de type par une base Object
tapez et ajoute les transtypages de type nécessaires. L’effacement de type permet à la fois la sécurité de type au moment de la compilation en fournissant des informations de type au compilateur ainsi qu’une compatibilité descendante en gardant le code d’octet le même que sur les versions Java précédentes. Pendant ce temps, l’effacement de type peut être limité lorsque vous avez besoin des informations de type dans une fonction générique.
Voyons maintenant comment reified
parvient à accéder aux informations de type au moment de l’exécution qui auraient dû être effacées au moment de la compilation. Pour résoudre ce problème, reified utilise des fonctions en ligne. Si vous n’êtes pas familier avec les fonctions en ligne, lisez cet article de blog.
Pour récapituler, si une fonction est marquée comme étant en ligne, le compilateur Kotlin copiera le corps de la fonction à chaque endroit où elle est utilisée. Un avantage de ceci est que le compilateur est également libre de modifier le corps de la fonction lors de sa copie. Pour utiliser des types de paramètres réifiés, vous devez d’abord rendre la fonction en ligne, puis ajouter le reified
mot-clé au paramètre générique.
Voyons ce qui se passe sous le capot dans le code Java décompilé. Lorsqu’il y a un appel à la fonction en ligne avec un type réifié, le compilateur copiera le corps de la fonction et remplacera les types génériques par le type déclaré réel. Par conséquent, vous n’avez pas besoin de réussir le cours pour accéder aux informations de type.
Reified ne peut être utilisé qu’avec des fonctions inline, donc les mêmes règles qui s’appliquent aux fonctions inline s’appliquent également à reified. N’oubliez pas non plus que les fonctions réifiées ne sont pas accessibles depuis Java. Java ne prend pas en charge l’inlining et sans l’inlining, les paramètres génériques ne peuvent pas échapper à l’effacement du compilateur.
Reified permet également aux fonctions de surcharge de renvoyer des types génériques. Par exemple, la fonction suivante peut renvoyer un Int
ou Float
.
Normalement, une fonction ne peut pas être surchargée avec la même entrée et avoir différents types de retour. Avec les fonctions en ligne, une fois encore, le compilateur peut remplacer le type de retour générique par le type attendu lors de la copie du corps de la fonction. Si vous regardez le code Java décompilé, le compilateur utilise un Integer
type pour le intCall
variable et utilisations Float
pour le floatCall
variable.