La meilleure façon de comprendre un langage, c'est d'y écrire du code. Pas de le lire, pas de regarder des webinaires, pas de sauvegarder des articles à « lire plus tard » (on sait tous comment ça finit). Kotlin de zéro : tutoriel pour débutants - 1Ouvrir un IDE et construire quelque chose qui fonctionne vraiment.

C'est exactement ce à quoi sert ce tutoriel. On va partir de zéro jusqu'à une première mini-application fonctionnelle. Si tu connais Java, ça ira encore plus vite — je ferai des parallèles tout au long.

Lancer Kotlin : deux options, l'une prend zéro minute

Directement dans le navigateur. Va sur play.kotlinlang.org et commence à écrire. Rien à installer, rien à configurer, pas de terriers Stack Overflow sur pourquoi le setup ne fonctionne pas. Parfait pour une première prise en main.

Dans IntelliJ IDEA. Le support Kotlin est intégré. Tu crées un nouveau projet Kotlin — et c'est prêt. Pas de plugins, pas de cérémonie.

Ton premier programme :

fun main() {
    println("Hello, Kotlin!")
}

En Java, la même chose ressemble à ça :

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Kotlin!");
    }
}

Les deux font exactement la même chose. Kotlin n'a juste pas de public static void ni de classe wrapper — parce que... pourquoi en avait-on besoin ? Bonne question. Java n'y a jamais vraiment répondu.

val et var : deux mots à retenir

En Kotlin, les variables se déclarent avec val ou var.

val name = "Alice"   // Immuable. Comme final en Java.
var age = 25         // Mutable.

age = 26             // OK.
name = "Bob"         // Erreur de compilation.

Règle simple : utilise val partout où la valeur n'a pas besoin de changer. var seulement quand tu as vraiment besoin de mutation. C'est comme se faire une promesse à l'avance : « Je ne vais pas changer ça. » Et Kotlin s'assure que tu la tiens.

Pas besoin de préciser le type — Kotlin l'infère :

val score = 100     // Kotlin comprend : c'est un Int
val name = "Alice"  // C'est un String

Ou explicitement, si tu préfères :

val score: Int = 100
val name: String = "Alice"

Null-safety : comment Kotlin élimine le NullPointerException

Tony Hoare a inventé null en 1965 et l'a ensuite appelé son « erreur à un milliard de dollars ». Ça ressemble à de l'autocritique — mais c'est en fait sous-estimer le problème. Le NullPointerException a coûté bien plus que ça à l'industrie.

En Java, n'importe quelle variable peut s'avérer null. Le compilateur reste silencieux. On le découvre en runtime. En production. Parfois lors d'une démo live chez un client — oui, ça arrive.

Kotlin résout ce problème au niveau du système de types :

var name: String = "Alice"
name = null  // Erreur de compilation. Immédiatement. Avant l'exécution.

Si une variable peut être null, il faut le préciser explicitement avec ? :

var name: String? = "Alice"
name = null  // On a convenu que c'est nullable — maintenant c'est OK.

Et quand on veut appeler une méthode sur quelque chose qui pourrait être null ?

println(name?.length)        // Si null — retourne null. Ne plante pas.
println(name?.length ?: 0)   // Si null — retourne 0. Opérateur Elvis.

Il s'appelle opérateur Elvis — parce que ?: ressemble à la coiffure d'Elvis Presley. Ce n'est pas une blague. C'est l'explication officielle dans la documentation.

Fonctions

En Java :

public static int add(int a, int b) {
    return a + b;
}

En Kotlin :

fun add(a: Int, b: Int): Int {
    return a + b
}

Ou encore plus court — pour les fonctions à une seule expression :

fun add(a: Int, b: Int) = a + b

Kotlin supporte les valeurs de paramètres par défaut. En Java, il faudrait écrire plusieurs méthodes surchargées. En Kotlin — une seule :

fun greet(name: String, greeting: String = "Salut") {
    println("$greeting, $name !")
}

greet("Alice")           // Salut, Alice !
greet("Bob", "Hé")       // Hé, Bob !

Les templates de string — $name directement dans la chaîne. Kotlin substitue la valeur de la variable. Pas de +, pas de concaténation — comme un langage sensé devrait fonctionner.

Data class : adieu le boilerplate

Tâche classique : on a besoin d'un modèle — un utilisateur avec un nom, un âge et un email.

En Java, ça veut dire un constructeur, trois getters, trois setters, equals(), hashCode(), toString(). Ou Lombok. Ou accepter son sort et tout écrire à la main comme en 2005.

En Kotlin :

data class User(val name: String, val age: Int, val email: String)

Une ligne. Le compilateur génère tout le reste, y compris copy() :

val alice = User("Alice", 30, "alice@example.com")
val olderAlice = alice.copy(age = 31)

println(alice)
// User(name=Alice, age=30, email=alice@example.com)

Regarde copy(). Tu crées un nouvel objet en modifiant uniquement les champs dont tu as besoin. En Java, tu écrirais généralement un Builder pour ça. Ou tu souffres.

Extension functions : ajouter des méthodes aux classes qu'on ne possède pas

Imagine que tu veux ajouter une méthode à la classe String. En Java — une classe utilitaire avec des méthodes statiques, et partout tu écris StringUtils.doSomething(myString). Ça marche, mais ça sent le bricolage.

En Kotlin — les extension functions :

fun String.isValidEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

println("user@example.com".isValidEmail())  // true
println("pas-un-email".isValidEmail())      // false

Ça se lit comme une méthode native de la classe. Pas d'héritage, pas de wrappers. Tu as juste ajouté une méthode — et tu l'utilises.

On assemble tout : un validateur d'utilisateurs

Prenons tout ce qu'on a vu et écrivons quelque chose de concret.

data class User(val name: String, val email: String?)

fun String.isValidEmail() = contains("@") && contains(".")

fun validateUser(user: User): String {
    val emailStatus = user.email?.let {
        if (it.isValidEmail()) "valide" else "invalide"
    } ?: "non renseigné"

    return "${user.name} : email $emailStatus"
}

fun main() {
    val users = listOf(
        User("Alice", "alice@example.com"),
        User("Bob", "bob-pas-email"),
        User("Charlie", null)
    )
    users.forEach { println(validateUser(it)) }
}

Résultat :

Alice : email valide
Bob : email invalide
Charlie : email non renseigné

Remarque : null est géré sans un seul if. Les opérateurs ?. et ?: s'en occupent élégamment. Charlie n'a pas renseigné son email — et pas de NPE. La vie est belle.

Ce n'était que le début

On a couvert les bases ici : variables, null-safety, fonctions, data classes, extension functions.

La suite est encore plus intéressante. Les coroutines — du code asynchrone sans douleur. Les sealed classes — une alternative puissante au switch qui ne te laissera pas oublier de traiter un cas. Les opérations fonctionnelles sur les collections — map, filter, reduce en une ligne.

Si tu veux apprendre Kotlin de manière structurée plutôt qu'en morceaux épars dans des onglets de navigateur — essaie notre cours. 62 niveaux, plus de 1 100 exercices avec vérification automatique, 3 projets pour ton portfolio. Le premier niveau est gratuit.

codegym.cc/fr/courses/kotlin

Continuer la lecture