Programmation Orientée Objet avec Kotlin : Classes, Objets et Interfaces

Définition des classes

En Kotlin, le mot-clé class permet de déclarer une classe. Une classe peut regrouper des propriétés, des méthodes, des constructeurs et des classes imbriquées.

class ProfilUtilisateur {
    var pseudo: String = "Anonyme"
    var niveau: Int = 1

    fun afficherInfos() {
        println("Joueur : $pseudo, Niveau : $niveau")
    }
}

Si une classe ne contient aucun corps (pas de propriétés ni de méthodes), les acoclades peuvent être omises : class ClasseVide.

Instanciation d'objets

Pour créer une instance, on appelle le constructeur comme une fonction classique (il n'y a pas de mot-clé new) :

val profil = ProfilUtilisateur()
profil.pseudo = "KotlinDev"
profil.niveau = 10

Constructeurs et Initialisasion

Kotlin distingue le constructeur primaire des constructeurs secondaires.

Constructeur primaire

Il est déclaré directement dans l'en-tête de la classe :

class Appareil(val marque: String, var prix: Double)

Bloc d'initialisation

Le mot-clé init permet d'exécuter de la logique lors de la création de l'objet, car le constructeur primaire ne peut pas contenir de code complexe.

class Appareil(val marque: String, var prix: Double) {
    init {
        println("Appareil de marque $marque enregistré avec un prix de $prix €")
    }
}

Constructeurs secondaires

Une classe peut définir des constructeurs additionnels via le mot-clé constructor. Si un constructeur primaire existe, chaque constructeur secondaire doit le déléguer.

class Dimension(val largeur: Int, val hauteur: Int) {
    // Délégation au constructeur primaire
    constructor(cote: Int) : this(cote, cote)
}

Héritage et Polymorphisme

Par défaut, toutes les classes en Kotlin sont final (non héritables). Pour autoriser l'héritage, utilisez le mot-clé open.

open class Vehicule {
    open fun klaxonner() {
        println("Bip bip !")
    }
}

class Moto : Vehicule() {
    override fun klaxonner() {
        println("Vroum vroum !")
    }
}

Classes Abstraites

Une classe abstraite ne peut pas être instanciée directement. Elle sert de modèle pour d'autres classes.

abstract class Instrument(val nom: String) {
    abstract fun jouer()
}

class Piano : Instrument("Piano") {
    override fun jouer() {
        println("Le piano joue une mélodie.")
    }
}

Classes Imbriquées et Internes

Une classe définie à l'intérieur d'une autre est "imbriquée" par défaut (elle n'accède pas aux membres de la classe parente).

class Externe {
    private val message = "Secret"

    class Imbriquee {
        fun test() = "Accès impossible au secret"
    }

    inner class Interne {
        fun lireSecret() = message // Accès possible via 'inner'
    }
}

Classes de Données (Data Classes)

Utilisées principalement pour stocker des données, elles génèrent automatiquement equals(), hashCode(), toString() et copy().

data class Livre(val titre: String, val auteur: String)

Classes Scellées (Sealed Classes)

Les classes scellées permettent de restreindre la hiérarchie d'héritage. Elles sont idéales pour représenter des états dans une application.

sealed class EtatReseau
class Succes(val code: Int) : EtatReseau()
class Erreur(val message: String) : EtatReseau()
object Chargement : EtatReseau()

Interfaces

Les interfaces définissent un contrat. Contrairement à Java 7, elles peuvent contenir des implémentations par défaut pour les méthodes.

interface Actionnable {
    val id: String
    fun executer()
    fun log() {
        println("Action $id en cours...")
    }
}

class Commande(override val id: String) : Actionnable {
    override fun executer() {
        println("Exécution de la commande.")
    }
}

Objets et Singletons

Le mot-clé object permet de définir un singleton (une instance unique).

object GestionnaireConfiguration {
    var theme: String = "Sombre"
}

// Utilisation : GestionnaireConfiguration.theme

Compagnons (Companion Objects)

Le companion object remplace les membres statiques de Java. Il est lié à la classe plutôt qu'à une instance.

class FabriqueCafe {
    companion object {
        fun preparerExpresso() = "Expresso prêt !"
    }
}

// Appel direct via la classe
val cafe = FabriqueCafe.preparerExpresso()

Ils peuvent également implémenter des interfaces, ce qui les rend puissants pour le pattern "Factory" :

interface Usine<T> {
    fun creer(): T
}

class Robot {
    companion object : Usine<Robot> {
        override fun creer(): Robot = Robot()
    }
}

Étiquettes: kotlin OOP DataClasses CompanionObject Inheritance

Publié le 9 juin à 22h56