Formation Kotlin

Takoyaki
36.9K views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

Les bases de Kotlin

la syntaxe

La syntaxe est très inspirée de Java, avec toutefois quelques particularités dont certaines seront vues ultérieurement

  • fichiers .kt
  • pas de ;
  • déclaration de variables avec val / var
  • typage postfixé
  • déclaration des fonctions avec fun
  • les fonctions sont des entités de première classe, au même titre que les classes
  • pas de new pour appeler un constructeur
  • les expressions de contrôle varient un peu
  • contrôle natif des types nullables
  • wildcards de généricité (extends ou super en Java) avec in et out
  • inférence de type

variables et typage

On déclare un variable avec var.

Kotlin fait de l'inférence de type, c'est-à-dire qu'il sait déduire le type. Mais une fois défini, le type reste figé !

Le mot clé val permet de déclarer une constante (mot clé final de Java).

Tout est objet, même les types primitifs (pas boxing / unboxing) : Boolean,Byte,Int, Long, String, Float, Double, Unit

Le type tableau s'écrit Array<T> avec T le type des éléments du tableau.

Le type Unit peut-être assimilé au type Void de java. Un fonction retourne Unit par défaut ! Pour des raison de cohérence dans l'aspect fonctionnel du language (toute fonction retourne quelque chose), une fonction qui ne retourne rien en théorie, retourne l'object Unit. Unit ne peut prendre en effet qu'une valeur unique, en comparaison Boolean en prend 2 : true et false.

Le type Any correspond à n'importe quel type, similaire au type Objet de java.

Les variables et fonctions peuvent être nommées de manière plus flexible grâce à ````. Utile pour nommer les tests unitaires, ou contourner les conflits de nommage (mockito.``when``(...))

Cast et Smartcast

Nous pouvons forcer le type d'une valeur avec l'opérateur as (unsafe cast operator) ou l'opérateur as? (safe cast operator).

is permet de tester le type d'une variable (cf. instanceof de Java). Intervient alors le SmartCast dans un bloc if ou when par exemple !

Égalité

L'opérateur == (double-égale) prend le sens du .equals() de Java.

L'opérateur === (triple-égale) prend le sens du == de Java, donc égalité sur la référence.

Les chaînes de caractères

Les chaines Multiligne peuvent être écrites sur plusieurs lignes.

Exemple:

Null safety

Kotlin sécurise l'exécution du code avec des types nullable, obligeant le développeur à prendre en compte les cas de nullité.

Exemple :

var nullable: String? = null
var nonNullable: String = ""

var nonNullable: String = null // erreur de compilation

Les types non-nullable, par définition, ne pourront pas être null, finis les if(item == null){…} !

Pour les types nullable, un arsenal d'opérateurs permettent de ne pas casser le flux de lecture du code.

  • ?. safe call : accès à une propriété / méthode si l'objet n'est pas null, retourne null sinon
  • ?: operateur elvis : retourner une valeur par défaut si null
  • !! forcer le cast vers un type non-null. NullPointerException si l'objet est effectivement null !

Sous le capot, les types nullables ne sont pas wrappés avec des classes Optional, mais annotés par @Nullable et @NotNull, ce qui améliore les performances.

les structures de contrôle

if

Même si le if Kotlin est très similaire au if java, il peut être utilisé en opérateur ternaire car il peut retourner une valeur.

for

L'instruction for itère sur tous les types d'objets itérables. Par exemple sur des ranges :

when

L'instruction when est un super switch Java, supportant des conditions complexes.

Exceptions

Toutes les exceptions en kotlin sont unchecked (cf. RuntimeException), c'est à dire qu'il n'est pas nécessaire d'encadrer systématiquement par des try/catch/Finally les méthodes qui emettent des exceptions.

Comme souvent en Kotlin, try peut retourner une valeur :

Le type Nothing est le type particulier d'une fonction qui ne retournera jamais rien, une fonction qui part en échec systématiquement.

fun fail(): Nothing {
    throw Exception("Failure")
}

Cependant, pour l'interoperabilité avec Java, nous pouvons indiquer que notre fonction envoi une exception avec l'annotation @Throws. Le code Java appelant devra alors l'inclure dans un try/catch.

@Throws(NumberFormatException::class)
fun parse(str:String): Int = str.toInt()

Fonctions

Les fonctions et méthodes sont déclarées sous la forme fun name(arg1:T, arg2:U):V { ... }.

On peut spécifier des paramètres par défaut très simplement, par exemple fun getWeather(date:LocalDate=LocalDate.now()){}. Cette fonction pourra être appelée avec getWeather()

À l'appel d'une fonction, les paramètres peuvent être nommés, sans se soucier de l'ordre de déclaration et améliorant la lisibilité.

fun doSomething(one:String, two:Int, three: Int = 0) {
    println("one=$one, two=$two, three=$three")
}
fun main(args:Array<String>){
    doSomething(two=2, one="ONE")
}

Une fonction dont le corps ne possède qu'une seule instruction (ou chaîne d'instructions), peut être écrite en expression body :

fun square(a:String) = a * a

Comme en Java, nous pouvons spécifier des arguments variables avec le mot clé vararg. Pour passer un tableau ou une collection à un argument variable, il suffit de le déstructurer avec *

Lambdas

Les lambda expressions sont déclarées sous la forme val name: (T, U) -> V = { arg1, arg2 -> ... }.

Dans une lambda avec un paramètre unique, celui peut alors être omis et se nomme it. On n'utilise pas le mot clé return pour la valeur de retour d'une lambda.

Si le dernier paramètre d'une fonction est une lambda expression, elle peut être sortie de la liste de paramètres de l'appel.

Quizz

Question 1

var a = 3
a = "Hello"
println(a) 
Quel est le contenu de a

Question 2

val value = 42
val regex = """\d\W$value"""
println(regex) 
Quel est le contenu de regex

Question 3

var message:String? = "Message"
var length = message?.length
Quel est le type de length ?

Question 4

fun upper(str:String? = "default") = str.toUpperCase()
Quel est le résultat de upper()

Question 5

// Fichier monpackage.MaFonction.kt
fun hello() = println("Hello")
Depuis Java, comment appelle t-on la fonction hello() ?

Question 6

val a = "2048"
val b = 2048.toString()
println("${a == b} ${a === b}")
Qu'affiche ce code ?

Question 7

val value = "Message"
println(value as? Int)
println(value as Int?)
Qu'affiche ce code ?

Exercices

FizzBuzz

Afficher les nombres de 1 à 100, mais afficher Fizz si le nombre est divisible par 3, Buzz s'il est divisible par 5 et FizzBuzz s'il est divisible à la fois par 3 et par 5.

Open Source Your Knowledge: become a Contributor and help others learn. Create New Content