📚 Fonctionnalités avancées de Kotlin

Propriétés déléguées

Kotlin permet de déléguer le getter et le setter d'une propriété à un autre objet, appelé délégué. C'est une classe qui définit les méthodes getValue et setValue.

Kotlin fournit des délégués standard tels que des propriétés paresseuses et des propriétés observables.

▶️ this codeopen in new window illustrates delegate properties.

Concurrence et coroutines

Kotlin fournit un modèle de concurrence de haut niveau appelé Coroutines. Le développeur peut déléguer la gestion des threads au compilateur et à l'exécution et utiliser des constructions de niveau supérieur aux threads pour exprimer des opérations asynchrones.

Les coroutines de Kotlin tournent autour de ces concepts :

  • Une coroutine est une instance de calcul suspendable.
    • Kotlin a de nombreuses mĂ©thodes pour crĂ©er une coroutine telle que launch.
  • Une coroutine doit exister dans une portĂ©e de coroutine.
    • Par exemple, runBlocking crĂ©e une portĂ©e de coroutine dans laquelle les coroutines peuvent ĂŞtre lancĂ©es.
  • Une coroutine peut exĂ©cuter des fonctions de suspension qui peuvent suspendre la coroutine mais ne bloquent pas le thread.
    • Par exemple : le delay suspend la coroutine mais ne bloque pas le thread sur lequel elle s'exĂ©cute.
    • Les fonctions de suspension sont des opĂ©rations qui peuvent prendre du temps telles que les requĂŞtes http et les appels au système de fichiers.
  • Le qualificateur suspend dĂ©finit une fonction de suspension. Il s'exĂ©cute dans une coroutine et peut appeler d'autres fonctions de suspension.
  • Flow permet de gĂ©nĂ©rer une liste de valeurs asynchrones.
  • Deferred et Channel transfèrent respectivement une valeur unique et un flux de valeurs entre coroutines.

▶️ this codeopen in new window show how to create a coroutine and suspend function and how to use them.

▶️ this codeopen in new window illustrated flows.

▶️ this codeopen in new window illustrates channels and deferred.

Littéral de fonction avec récepteur et constructeurs de type sécurisé

Comme vu précédemment, les extensions de fonctions ajoute du comportement à des classes existantes sans utiliser l'héritage. À l'intérieur de la définition de l'extension de fonction, nous pouvons référencer implicitement le récepteur d'extension (this).

fun String.countCharacters() = length // or this.length
println("hello".countCharacters()) // prints 5

Nous pouvons définir cette extension avec une fonction littérale (ou lambda) au lieu d'une fonction classique (déclarée avec fun).

var extFn: String.() -> Int
extFn = { length } // extFn is a function literal
println("hello".extFn()) // prints 5
println(extFn("hello")) // prints 5

extFn est une fonction littérale (lambda) qui a accès au récepteur (this). C'est pourquoi on l'appelle une fonction littérale avec récepteur.

extFn("hello") ou extFn("hello") appelle l'extension comme prévu par les fonctions d'extension.

Le type d'une fonction littérale avec récepteur est funName: ReceiverType.(arg1Type, arg2Type, etc.) -> ReturnType et est appelé avec funName(receiverValue, arg1Value, etc.) ou receiverValue.funName(arg1Value, etc.) .). Cependant, ce n'est pas l'aspect le plus intéressant.

La partie importante est extFn = { length } qui peut être placée comme argument de fonction dans une fonction d'ordre supérieur. Le développeur qui appelle la fonction d'ordre supérieur doit définir extFn, qui à son tour a accès au récepteur. Cela permet un style de programmation assez intéressant.

▶️ ce codeopen in new window montre un example.

Les Type-safe buildersopen in new window combinent les monteurs bien nommées et les fonctions littérales avec récepteur pour créer des monteur avec un typage statique et sécurisé. La syntaxe particulière possible avec technique permet de définir une sorte de sous-langage aussi appelé DSL (domain specific language).

Le pattern monteur (Builder)

Est une technique permettant de construire des objects avec une syntaxe éléganteopen in new window.

// StirngBuilder uses the builder pattern
val text = StringBuilder("Temp")
  .append(1)
  .append(true)
  .append("friend")
  .toString()

Ce code montreopen in new window un type-safe builder basique.

Kotlin docsopen in new window fournit un exemple plus avancé d'un monteur de documents HTML.

Exercises

Exercise 1

  1. open the java-integration-exercise projects in the materials folder.
  2. Have a look at the Java class we provided you in the src/main/java/com/worldline/learning/kotlin/java2kotlin package. (yes, that's the Pokemon class)
  3. Convert that Java class in Kotlin using IntelliJ's awesome copy-pasta tool! (just copy paste the java code in a kotlin file, one is provided at src/main/kotlin/com/worldline/learning/kotlin/java2kotlin)
  4. Have a look at the generated Kotlin code, and note the major differences you spot!