--- title: 🍑 Kotlin découverte tags: android, campus numerique, kotlin, dim --- ![](https://i.imgur.com/zdaZFxT.png) ## Une histoire de syntaxe Kotlin est un langage développé par [Jetbrains](), Jetbrains développe des environnements de développement pour pratiquement tous les langages les plus utilisés. Kotlin en lui même est un langage **fonctionnel** et **orienté objet**. Là où java est 100% **orienté objet**, Kotlin permet plus de liberté d'utilisation et est ce qu'on appelle un langage moderne. Il est bien moins verbeux que Java. Permet de faire moins d'erreur, produit des programmes plus stables, et est plus flexible. Un exemple pour créer un POJO (ceux qui connaissent en Java sinon renseignez-vous c'est un principe de base) en Kotlin : ```kotlin= data class Customer(val name: String, val email: String, val company: String) ``` Et voila, cette ligne de code vous permet de créer une classe avec tout les getters, setters, `equals()`, `hashCode()`, `toString()` et `copy()`. :::info **Question 1** 👉 Définissez la différence entre objet, orienté objet et fonctionnel ? Comment qualifie-t-on ces concepts ? Qu'est ce qu'un POJO ? ::: ## Fonctionnement Kotlin permet de générer du bytecode pour JVM. ### Un mot sur la JVM La Java Virtual Machine est une belle invention qui date de 1995, et qui permet de faire un développement multi-plateforme. C'est un langage qui est compilé et interprété. :::info **Question 2** 👉 Définissez la différence entre un langage interprété et un langage compilé ? Citez quelques exemples de langage. ::: ![](https://i.imgur.com/ZsuHomE.png =350x) Lorsque vous codez en *Java*, votre code est compilé en `byte code` ce n'est pas un état directement interprétable par votre ordinateur, mais interprétable par une *JVM*. On appelle ça le **build time**. Ce byte code est ensuite interprété lorsque vous lancez votre application sur l'appareil cible, on appelle ça le **runtime**. D'où le besoin d'avoir un `JRE` (Java Runtime Environment) pour executer un programme *Java* sur votre machine. Mais le langage permet de compiler vers d'autres `byte code` ou `binary code` : - `Javascript` - `C/C++` - `Swift` - `ObjectiveC` - Any native executable ## Hello world ### Comment coder en Kotlin pour apprendre ? Vous avez l'embarras du choix: - Via [Intellijea IDE](https://www.jetbrains.com/fr-fr/idea/) - En [ligne de commande via le compilateur Kotlin de votre système](https://hackmd.io/@anthonydacruz/BJ0HFCB5H#Kotlin-en-ligne-de-commande) - Via [Gradle et mon tuto custom](https://hackmd.io/@anthonydacruz/BJ0HFCB5H) - Via [Kotlin Koans](https://play.kotlinlang.org/koans) un cours en ligne interactif - Via le [Playground en ligne](https://play.kotlinlang.org/) - Via la [documentation de Kotlin](https://kotlinlang.org/docs/reference/basic-syntax.html) :::success Pour des raisons de simplicité de configuration, je vous conseil d'utiliser le playground Kotlin en ligne. ::: ### Le *Hello world* --------- Dans le playground vous devriez avoir déjà une fonction main et le Hello world ```kotlin= //Kotlin fun main() { println("Hello world") } ``` ------- Voici le code équivalent en `Java` ```java= //Java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello world!"); } } ``` > **📝 Note** Dans les deux cas il vous faut un point d'entrée `main` à votre programme. En Kotlin c'est une simple fonction déclarée avec le mot clé `fun` en java il vous faut une classe et à l'interieur une méthode `main` ## Kotlin et le typage Kotlin est un langage fortement typé. :::info **Question 3** 👉 Définissez les points de différence entre un langage fortement typé et faiblement voire non typé ? Citez quelques exemples de langage. ::: Pour déclarer une variable en Kotlin ```kotlin= //On précise le type ici val myHelloWorldStringVariable:String = "Hello there" //Version alternative : //L'inférence de type permet d'éviter d'expliciter le type val myHelloWorldStringVariable = "Hello there" ``` > **📝 Note** On peut déclarer une variable en dehors de toute fonction ou classe, ce qui n'est pas possible en `Java` ------ Voici le code équivalent en `Java` ```java= public class HelloWorld { String myHelloWorldStringVariable = new String("Hello there"); public static void main(String[] args) { System.out.println("Hello world!"); } } ``` ## Les variables Pour déclarer une variable on peut utiliser 2 mots clés : `val` et `var` :::info **Question 4** 👉 Chercher la différence entre les deux mots clés et expliquer avec vos mots à l'enseignant. ::: ### Optional & Null safety 🌮 Attention on arrive à un endroit légèrement difficile. Du moins c'est pas commun sur les langages que vous avez vu jusqu'à aujourd'hui. En kotlin on ne peut pas avoir une valeur `null` dans une variable. Contrairement au `Java`. En Java on peut faire ca : ```java= public class HelloWorld { // arguments are passed using the text field below this editor public static void main(String[] args) { OtherClass otherClass = null; //Ici j'obtiens le fameux "Null pointer exception" lors du runtime System.out.print(otherClass.myVar); } } public class OtherClass { String myVar = new String("Hello"); } ``` 🚫 Si je compile ce code en Java, il va compiler (**Buildtime**) sans problème. Mais lorsque que je vais lancer mon programme (**Runtime**) il va planter. Ce qui est pas top, car je ne vois le problème qu'au moment ou l'utilisateur va lancer le programme. ---------- Essayons de faire la même chose en Kotlin Ajoutez dans votre fichier (`main.kt`) de test le code suivant : ```kotlin= fun main() { val otherClassInstance = OtherClass() println(otherClassInstance.myVar) } class OtherClass(var myVar:String = null) ``` :::info **Question 5** 👉 Que se passe-t'il lorsque vous compilez ? ::: 🚫 C'est impossible. En Kotlin si on indique pas **explicitement** qu'une variable peut contenir une valeur `null` alors c'est impossible de `build`. #### Comment on indique cela alors ? Si je voulais que le *build time* passe sur mon code Kotlin, il faudrait que je modifie en faisant cela : ```kotlin= fun main() { val otherClassInstance = OtherClass() println(otherClassInstance.myVar?) } //On a rajouté un signe "?" derrière notre type. //Cela indique au compilateur que cette variable est parfois "null" class OtherClass(var myVar:String? = null) ``` Non seulement cela compile, mais au runtime cela ne plante pas, même si votre variable est `null`. #### Comment gérer ce comportement ? Souvent dans votre code vous allez devoir indiquer au programme que vous n'êtes pas certain qu'il y aura une valeur *non null* dans une variable à un instant T (Ex: je récupère une donnée du réseau) Dans ce genre de cas, vous allez devoir `unwrap 🌮` la variable, c'est en gros "Découvrir" ce qu'il y a dedans, et suivant ce que vous trouverez, exécutez tel ou tel code. Si je prend l'exemple du réseau, imaginez le code suivant ```kotlin= //Je vais stocker la réponse hypothétique du réseau dans ma variable var myNetworkResponse:String? = null //Ici j'appelle le réseau, et il renvoi une valeur (ou PAS) myNetworkResponse = networkCall() //Je veux récuperer la réponse du réseau si il y en a unne myNetworkResponse?.let { //La fonction `let` permet de unwrap 🌮 votre variable //Elle produit une valeur non optionnel "it" par defaut saveNetworkResponseToDataBase(it) //"it" est certain d'exister, et est non null } ``` :::info **Question 6** 👉 Selon vous quelle est la signature de la fonction `networkCall` ? Ecrivez la et faites valider par l'enseignant. ::: > **Note 📝** Cette fonction n'existe pas, on vous demande à partir du code ci-dessus d'imaginer sa signature --- > **Note 📝** Le même exemple mais avec le nommage explicite de la donnée `unwrap 🌮` ```kotlin= //On donne un nom explicite "responseData" au lieu de "it" myNetworkResponse?.let { responseData -> //La fonction `let` permet de unwrap 🌮 votre variable saveNetworkResponseToDataBase(responseData) } ``` On a vu la fonction `let` mais il en existe d'autres pour gérer les optionnels et le `null safety` Pour en apprendre plus [voici un lien vers la documentation Kotlin qui explique ce comportement et comment l'utiliser au mieux.](https://kotlinlang.org/docs/reference/null-safety.html) :::info **Question 7** 👉 Comment pourriez vous faire pour exécuter du code dans le cas ou la valeur de l`unwrapping 🌮` est effectivement `null`, pour déclencher un nouvel appel réseau par exemple ? Trouvez l'opérateur adéquat et inscrivez le code d'exemple complété dans un ficher. ::: ### Attention ⚠️ A l'inverse vous pouvez forcer le compilateur à ignorer qu'une variable est potentiellement `null` Grâce au symbole `!!` : il est à éviter le plus possible car il force le compilateur à ne pas vérifier si cette variable est vide avant de l’utiliser. Cela peut être pratique pour éviter l’`unwrapping 🌮` et donc quelques lignes de code, mais c’est aussi très dangereux car le comportement est imprévisible. ```kotlin= //On bourrine. Mais si le network plante, le programme plante. saveNetworkResponseToDataBase(myNetworkResponse!!) ``` ![](https://i.imgur.com/et4S9Ph.jpg) ## Les fonctions En Kotlin vous pouvez déclarer des fonctions n'importe où dans votre programme. Une fonction peut aussi être dans une variable, comme en `javascript`. ```kotlin= fun myFunction() fun myFunction(): String { return "Hello World" } //Type inference, Kotlin devine que la fonction sera de type string. //On utilise également la syntaxe simplifiée pour une fonction ici fun myFunction() = "Hello world" //Avec un parametre, les parametres doivent-etre typé fun numberOfCharactersInString(inputString: String): Int { return parameter.length } fun greetUser(name: String, lastname:String, city:String) { println("Hello $name $lastname, you live in $city") } //Lambda dans une variable var myVariable = { println("Hello") } //On peut aussi passer des parametres var myVariable:(name: String) -> Unit = {name -> println("Hello $name") } //Fonction anonyme ex 1 val square = fun(x: Int) = x * x //Fonction anonyme ex 2 val greetings = fun(name: String) = "Hello $name" ``` Puisque Kotlin est aussi un langage fonctionnel, il est important de bien comprendre comment et quand utiliser des fonctions. Nous verrons tout au long de l'introduction différents moyens d'utiliser les fonctions et variables. > **Note 📝:** La syntaxe pour concatener une `string` est `+` ou à l'intérieur des double quote vous pouvez utiliser `"Je concatene avec $maVariable"`. Et pour accéder a une propriété de votre variable : `"Je concatene avec ${maVariable.maProp}"` ### Appeler une fonction Il existe plusieurs façon d'appeler une fonction en Kotlin, notamment au niveau des paramètres. :::success Dans le langage les paramètres sont nommés, même si on est pas obligé de préciser le nom du paramètre c'est très utile pour s'y retrouver. ::: ```kotlin= numberOfCharactersInString("Hello"); //5 //J'appelle ma fonction en précisant le nom des parametres numberOfCharactersInString(inputString = "Hello") ``` ## Control flow (`if`, `for`, `when`) Je ne vais pas paraphraser [la documentation qui fait très bien son boulot ici](https://kotlinlang.org/docs/reference/control-flow.html). :::info **Question 8** 👉 Quel est l'équivalent du `switch` en kotlin ? ::: :::info **Question 9** 👉 Créez un tableau de `string` et affichez chaque valeur dans la sortie console. Faites valider par l'enseignant. ::: ## Les classes Kotlin est aussi un langage objet, on déclare une classe qui possède une propriété comme ceci : ```kotlin= //Le constructeur est dans la signature de la classe entre () class MyClass(val myProperty:String?) //Pour instancier cette classe val myClassInstance = MyClass("hello") ``` Ou ```kotlin= class MyClass { var myVar:String? = null constructor(myVarValue: String?){ myVar = myVarValue } } ``` Sans propriété : ```kotlin=+ class MyClass ``` ------ Voici le code équivalent en `Java` ```java= class MyClass { String myProperty; public MyClass(String myProperty){ this.myProperty = myProperty; } } ``` Il est très rapide et concis de créer une classe en Kotlin. Et puisque c'est un langage assez malin il y a pas mal de raccourcis sous forme de mot clés. ### Les classes de données Un concept qui n'existe pas partout, les `data class` sont en fait un type de classe dédié au stockage de la donnée. La différence avec les classes normales est que le compilateur va vous créer automatiquement des fonctions utilitaires sur vos `data class`. Les fonctions automatiquement générées : - `equals()` - `toString()` - `hashCode()` - `copy()` - `...` > [Retrouvez la documentation sur les data class](https://kotlinlang.org/docs/reference/data-classes.html) Exemple de `data class` ```kotlin= data class User(val name: String, val age: Int, val gender: Gender) val myUser = User(name = "Roger", age = 21, gender = Gender.MALE) //To string est généré automatiquement donc tout va bien println(myUser) ``` Encore une fois on remarque qu'un mot clé du langage va nous permettre de gagner du temps sur le développement tout en gardant des concepts standards. > Remarquez le type `Gender`, c'est un `enum` en Kotlin vous pouvez utiliser ce genre de variable pour définir un set de valeur prédéfini pour un objet. ## Classes `Enum` Très simple a comprendre mais redoutablement efficace pour construire un programme très robuste, les classes `enum` permettent de lister des valeurs possibles d'un type donné. Exemple avec notre `Gender` ```kotlin= enum class Gender { FEMALE, MALE, OTHER } ``` Cela permet d'éviter d'hardcoder des valeurs et d'éviter d'utiliser des constantes `String` qui sont fastidieuses à travailler et génératrice d'erreur. ```kotlin= data class User(val name: String, val age: Int, val gender: Gender) val user1 = User(name = "Roger", age = 21, gender = Gender.FEMALE) ``` Ainsi toute variable ayant le type `Gender` ne pourra prendre qu'une des 3 valeurs de l'`enum` possible. :::info **Question 10** 👉 Trouvez 3 exemples de classe enum qui vous permettrait de simplifier un problème ? ::: ## Les mots clés `Companion, Object, Lateinit, let, with, run` ne représentent qu'une partie émergée de l'iceberg. Kotlin est un langage avec beaucoup de mots-clés :key: :key: :key: , [en voici une référence](https://kotlinlang.org/docs/reference/keyword-reference.html). :::info **Question 11** 👉 Codez un programme faisant l'usage d'un singleton, en utilisant le mot-clé approprié. ::: ## Que faire maintenant ? Pour apprendre et maitriser un nouveau langage, il n'y a pas de solution simple. **Il faut vous entrainer** Un lien pour apprendre de la meilleure manière le Kotlin : - https://play.kotlinlang.org/koans/overview