Notez que toutes les nouvelles fonctions sont ajoutées à la bibliothèque standard à l'état expérimental.
Extension de StringBuilder dans la bibliothèque commune
StringBuilder était déjà présent dans la bibliothèque standard commune, dans le package kotlin.text. Cependant, de nombreux membres importants manquaient à l'appel ou n'étaient disponibles que sur la machine virtuelle Java. Désormais, toutes les fonctionnalités JVM de StringBuilder ont été ajoutées à la class expect commune avec les implémentations correspondantes sur différentes plateformes. Cela signifie que vous pouvez utiliser efficacement StringBuilder à partir du code commun car tous les membres nécessaires sont là.
Travailler avec KClass
Certains membres utiles de base de KClass ne nécessitent plus de dépendance kotlin-reflect sur la machine virtuelle Java:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | import kotlin.reflect.cast @OptIn(ExperimentalStdlibApi::class) fun main() { val kClass = String::class println(kClass.simpleName) // String println(kClass.qualifiedName) // kotlin.String println(kClass.isInstance("abc")) // true println(kClass.isInstance(10)) // false println(kClass.cast("abc")) // abc } |
Renommage des annotations expérimentales (@Experimental et @UseExperimental)
Comme vous le savez peut-être, Kotlin a un mécanisme intégré pour utiliser des fonctionnalités expérimentales. Il comprend des annotations de la bibliothèque standard, qui marquent des déclarations qui sont soit expérimentales elles-mêmes, soit utilisent d'autres déclarations expérimentales. Dans les versions précédentes, il s'agissait de @UseExperimental et @Experimental.
JetBrains a décidé d'élargir le champ d'application de ce mécanisme, car un élément à l'état expérimental n'est pas la seule raison d'exiger le consentement pour utiliser des API. Par exemple, une API peut être interne ou avoir certaines restrictions. JetBrains a renommé les annotations pour refléter cela : les noms @OptIn et @RequiresOptIn ont remplacé @UseExperimental et @Experimental, en conséquence. L'argument du compilateur -Xuse-experimental a été renommé en -Xopt-in. Quant à -Xexperimental, il a été abandonné car il est rarement utilisé et augmente la complexité. Les anciennes déclarations @Experimental et @UseExperimental sont toujours prises en charge dans la version 1.3.70, mais seront supprimées dans la version 1.4.
Changement de nom de l'API expérimentale de mesure du temps
Un autre changement de nom que JetBrains a fait concerne l'API de mesure de la durée et de l'heure. Clock et ClockMark ont été renommés TimeSource et TimeMark en conséquence. Les noms précédents sont conservés en tant qu'alias de type obsolètes pour l'instant.
Implémentation de file d'attente à double extrémité: ArrayDeque
JetBrains a annoncé l'ajout de l'implémentation de la file d'attente double, la classe kotlin.collections.ArrayDeque, à la bibliothèque standard de Kotlin! La communauté le demande depuis un certain temps. Même si vous pouviez utiliser la classe java.util.ArrayDeque de la bibliothèque standard Java, il n'y avait aucune implémentation commune que vous pouviez utiliser pour Kotlin / JS, Kotlin / Native et, surtout, dans le code commun. Maintenant, une telle implémentation est disponible, bien qu'à l'état expérimental.
Une file d'attente à double extrémité vous permet d'ajouter / supprimer des éléments à la fois au début et à la fin de la file d'attente en temps constant amorti:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @OptIn(ExperimentalStdlibApi::class) fun main() { val deque = ArrayDeque(listOf(1, 2, 3)) deque.addFirst(0) deque.addLast(4) println(deque) // [0, 1, 2, 3, 4] println(deque.first()) // 0 println(deque.last()) // 4 deque.removeFirst() deque.removeLast() println(deque) // [1, 2, 3] } |
Vous pouvez utiliser une file d'attente à double extrémité par défaut lorsque vous avez besoin d'une file d'attente ou d'une pile dans votre code.
L'implémentation kotlin.collections.ArrayDeque utilise un tableau redimensionnable en dessous: elle stocke le contenu dans un tampon circulaire, un tableau, et ne redimensionne ce tableau que lorsqu'il est plein.
Conceptuellement, l'implémentation d'ArrayDeque est très similaire à celle de java.util.ArrayDeque. Notez cependant qu'il s'agit d'une implémentation différente et que cette nouvelle implémentation sera utilisée lorsque vous utiliserez cette classe pour Kotlin / JVM. Cela diffère de la façon dont cela fonctionne avec d'autres collections: lorsque vous créez un ArrayList et le compilez sur JVM, la classe java.util.ArrayList est utilisée sous le capot. Contrairement à ArrayDeque de Java, qui implémente uniquement l'interface Collection, ArrayDeque de Kotlin implémente MutableList. Cela signifie que vous pouvez accéder à tous les éléments par index, ce qui n'est pas possible dans ArrayDeque de Java.
reduceOrNull() et randomOrNull()
Vous connaissez cette convention dans Kotlin : avoir une paire de fonctions, où la première lève une exception si l'opération n'est pas possible, et la seconde renvoie null, comme [C]string.toInt()[C] et string.toIntOrNull(). L'éditeur a ajouté de nouvelles fonctions homologues randomOrNull() et reductionOrNull(), suivant la même convention.
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | @OptIn(ExperimentalStdlibApi::class) fun main() { val list = listOf(1, 2, 3) println(list.randomOrNull()) // 2 println(list.reduceOrNull { a, b -> a + b }) // 6 val emptyList = emptyList<Int>() println(emptyList.randomOrNull()) // null println(emptyList.reduceOrNull { a, b -> a + b }) // null } |
Si vous utilisez random() ou reduce(), vous obtiendrez une exception si la collection est vide.
Les fonctions scan
Kotlin 1.3.70 s'accompagne d'un nouvel ensemble de fonctions pour travailler avec des listes et des séquences. Elles représentent le concept de « scanner »; des fonctions similaires sont déjà présentes dans différentes bibliothèques et langages.
scan() est étroitement lié à fold(). scan() et fold() appliquent à la fois l'opération binaire donnée à la séquence de valeurs, mais diffèrent en ce que scan() renvoie la séquence entière des résultats intermédiaires, tandis que fold() ne renvoie que le résultat final.
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 7 8 | @OptIn(ExperimentalStdlibApi::class) fun main() { val ints = (1..4).asSequence() println(ints.fold(0) { acc, elem -> acc + elem }) // 10 val sequence = ints.scan(0) { acc, elem -> acc + elem } println(sequence.toList()) // [0, 1, 3, 6, 10] } |
Prise en charge d'IntelliJ IDEA
Cette version inclut plusieurs améliorations pour la prise en charge de Kotlin dans IntelliJ IDEA. Passons en revue les plus intéressants.
Prise en charge de *.gradle.kts
En 1.3.70, JetBrains a travaillé pour améliorer la prise en charge d'IntelliJ IDEA pour les scripts Gradle Kotlin DSL (fichiers *.gradle.kts). En conséquence, la dernière version du plugin Kotlin présente de meilleures performances dans la mise en évidence de la syntaxe, la complétion, la recherche et d'autres aspects du travail avec les scripts de construction Kotlin.
Pour profiter de toutes les modifications et améliorations, assurez-vous d'utiliser IntelliJ IDEA 2019.2 ou version ultérieure avec Gradle 6.0 ou version ultérieure.
Complétion du code
Dans la version 1.3.70, JetBrains a apporté des améliorations notables à la complétion du code Kotlin dans IntelliJ IDEA. Désormais, les suggestions d'achèvement incluent les fonctions déclarées dans les objets, y compris les fonctions d'extension, les remplacements au niveau de l'objet et même les fonctions déclarées dans les objets imbriqués.
JetBrains a également amélioré le modèle d'apprentissage automatique qui trie la liste des complétions et maintenant, les options les plus pertinentes apparaissent en haut.
Nouveaux schémas de couleurs
Pour vous permettre de modifier l'apparence du code Kotlin dans l'éditeur à votre convenance, JetBrains a ajouté de nouveaux schémas de couleurs personnalisables. En particulier, vous pouvez désormais définir vos propres schémas de couleurs pour les appels de fonction de suspension et les déclarations de propriétés.
Améliorations du débogage
Dans les versions précédentes, le débogueur Kotlin/Native avait un type de point d'arrêt distinct, ce qui confond certains utilisateurs avec un choix peu clair comme «quel type de point d'arrêt dois-je utiliser ici?». Désormais, le type de point d'arrêt unique Kotlin Line Breakpoint fonctionne pour les cibles JVM et Native.
Tests Kotlin/JS et Kotlin/Native
Les résultats des tests pour Kotlin/JS et Kotlin/Native sont désormais affichés directement dans IntelliJ IDEA, comme cela a toujours été le cas pour les tests Kotlin/JVM. En outre, JetBrains a corrigé le filtrage des tests pour Kotlin/JS, de sorte que vous pouvez exécuter des tests individuels, et les tests Kotlin/Native ciblant le simulateur iOS peuvent enfin également être lancés directement en appuyant sur le bouton "Play".
Kotlin/JVM
Kotlin peut désormais générer des annotations de type dans le bytecode JVM (version cible 1.8+), afin qu'elles deviennent disponibles au moment de l'exécution. Cette fonctionnalité est demandée par la communauté depuis un certain temps, car elle facilite l'utilisation de certaines bibliothèques Java existantes et donne plus de pouvoir à ceux qui créent de nouvelles bibliothèques.
Dans l'exemple suivant, l'annotation @Foo sur le type String peut être émise vers le bytecode puis utilisée par le code de la bibliothèque:
Code Kotlin : | Sélectionner tout |
1 2 3 4 5 6 | @Target(AnnotationTarget.TYPE) annotation class Foo class A { fun foo(): @Foo String = "OK" } |
Pour émettre l'annotation de type dans le bytecode, procédez comme suit:
- Assurez-vous que votre annotation déclarée a une cible d'annotation appropriée (ElementType.TYPE_USE de Java ou AnnotationTarget.TYPE de Kotlin) et rétention (AnnotationRetention.RUNTIME).
- Compilez la déclaration de classe d'annotation et le code à l'aide de cette annotation (classe A dans l'exemple ci-dessus) vers la version cible 1.8+ du bytecode JVM. Vous pouvez le spécifier avec l'option de compilateur -jvm-target = 1.8.
- Compilez le code à l'aide de l'annotation avec l'option de compilateur -Xemit-jvm-type-annotations.
Kotlin/JS
Avec Kotlin 1.3.70, la cible JavaScript reçoit quelques optimisations importantes en termes de taille de bundle et ajoute quelques changements de qualité de vie à la façon dont les dépendances, les ressources et les tests sont traités.
Optimisations des bundles
À partir de Kotlin 1.3.70, DCE (Dead Code Elimination) est maintenant facilement disponible via le plugin org.jetbrains.kotlin.js Gradle et n'a pas besoin d'être ajouté manuellement. Il reçoit un ensemble de nouvelles tâches que vous pouvez utiliser pour contrôler l'optimisation et l'exécution de votre projet JS.
Pendant le développement, utilisez browserDevelopmentRun pour démarrer une exécution non optimisée de votre application avec le serveur de développement fourni et utilisez browserDevelopmentWebpack pour créer un ensemble non optimisé de votre application dans le dossier build / distributions. Si vous choisissez de ne pas exécuter d'optimisations, vos temps de génération seront plus rapides, mais les programmes compilés auront des fichiers plus volumineux.
Lors de la préparation de la production, utilisez browserProductionRun pour démarrer une exécution optimisée de votre application et utilisez browserProductionWebpack pour générer un ensemble optimisé adapté au déploiement en production. Les compilations de production prennent un peu plus de temps à compiler, mais se retrouvent avec un ensemble beaucoup mieux optimisé que leurs homologues de développement.
Copie automatique des ressources
Les tâches de génération qui créent des ensembles dans le dossier de distributions (comme browserProductionWebpack) copient désormais également tous les actifs du dossier de ressources, il n'est donc plus nécessaire de copier manuellement les images, les feuilles de style et autres pour obtenir un ensemble déployable d'artefacts.
Prise en charge plus fluide des déclarations de dépendance npm
Lorsque vous utilisez le plugin Kotlin / JS Gradle, il est désormais possible de déclarer les dépendances npm à l'intérieur du bloc de dépendances de niveau supérieur, au lieu d'avoir à ajouter manuellement un ensemble de sources principal. Cela signifie que l'extrait de code suivant est désormais valide:
Code Gradle-build : | Sélectionner tout |
1 2 3 | dependencies { implementation(npm("react", "16.12.0")) } |
Kotlin / Native
Optimisations des performances
Les performances de compilation étaient l'un des points faibles connus du développement Kotlin/Native, JetBrains a donc proposé deux nouvelles fonctionnalités pour réduire les temps de compilation:
- Maintenant, le compilateur Kotlin / Native s'exécute directement à partir du démon Gradle, donc aucun temps n'est consacré au démarrage d'un nouveau processus et au chargement du compilateur dans chaque compilation.
- En mode débogage, le compilateur met en cache les dépendances du projet. Désormais, la première compilation prend un peu plus de temps, mais les suivantes se terminent plus rapidement. Notez qu'à l'heure actuelle, cela ne fonctionne que pour le simulateur iOS (iosX64) et macOS (macosX64); JetBrains y travaille toujours.
Prise en charge de plusieurs frameworks Kotlin dans une seule application
Auparavant, il existait un problème connu selon lequel une application ne pouvait pas utiliser plus d'une infrastructure Kotlin / Native dynamique car les classes Obj-C définies lors de l'exécution étaient en conflit, provenant de différentes instances de l'exécution. JetBrains a corrigé cela dans 1.3.70 ; désormais, une application peut utiliser plusieurs frameworks Kotlin/Native. Toutes les dépendances courantes sont présentes dans les frameworks sous différents modules Swift (et avec différents préfixes Obj-C).
Source : JetBrains