Menu
Coddy logo textTech

Constantes avec const

Fait partie de la section Programmation orientée objet du Journey Kotlin de Coddy. Leçon 14 sur 57.

const val déclare une constante à la compilation : une valeur qui est fixée lorsque le programme est compilé. Elle est autorisée au niveau supérieur d’un fichier et à l’intérieur d’un object ou d’un companion object, et uniquement pour les types de base tels que Int, Double et Boolean, ainsi que pour String :

const val MAX_PLAYERS = 4

class Lobby {
    val players = mutableListOf<String>()

    fun canStart() = players.size in MIN_PLAYERS..MAX_PLAYERS

    companion object {
        const val MIN_PLAYERS = 2
    }
}

À l’intérieur de main :

val lobby = Lobby()
lobby.players += listOf("ada", "bo")
println(lobby.canStart())
println("${Lobby.MIN_PLAYERS}-$MAX_PLAYERS players")

Sortie :

true
2-4 players

Les constantes sont nommées en UPPER_SNAKE_CASE. const est plus strict que val : la valeur doit être connue sans exécuter de code, donc un appel de fonction ou une liste n’est pas autorisé. Un val dans un objet est également partagé et accessible en lecture seule, et accepte n’importe quelle valeur :

const val GREETING = "Hello"                  // un littéral String
const val TIMEOUT_MS = 30 * 1000              // calculé à partir de littéraux
// const val START = System.nanoTime()        // erreur : ce n'est pas une constante
// const val DAYS = listOf("Mon", "Tue")      // erreur : seulement les types de base et String
object Defaults {
    val DAYS = listOf("Mon", "Tue")           // un val partagé en lecture seule
}

Un objet compagnon peut également contenir un état mutable partagé. Chaque instance lit et modifie la même propriété, ce qui convient aux compteurs et aux caches. Cette classe conserve une instance par nom ; ainsi, deux demandes renvoient le même objet (=== vérifie que deux références pointent vers un seul objet) :

class Tile private constructor(val name: String) {
    companion object {
        private val cache = mutableMapOf<String, Tile>()
        val created: Int
            get() = cache.size

        fun of(name: String) = cache.getOrPut(name) { Tile(name) }
    }
}

Dans main :

val a = Tile.of("grass")
val b = Tile.of("grass")
Tile.of("water")
println(a === b)
println(Tile.created)

Sortie :

true
2

Au niveau supérieur ou dans un compagnon ? Une constante ou une fonction de niveau supérieur appartient à son fichier et est utilisée sous son nom simple dans chaque fichier du paquet. Placez une constante dans un compagnon lorsqu’elle appartient à une seule classe : les appelants écrivent Lobby.MIN_PLAYERS, ce qui indique d’où vient la valeur, et un private const val reste à l’intérieur de cette classe.

// Limits.kt
const val MAX_UPLOAD_MB = 25                 // utilisé partout comme MAX_UPLOAD_MB

// Lobby.kt
class Lobby {
    companion object {
        const val MIN_PLAYERS = 2            // utilisé comme Lobby.MIN_PLAYERS
        private const val ROOM_PREFIX = "L-" // uniquement à l'intérieur de Lobby
    }
}
challenge icon

Défi

Facile

Complétez la classe Order(val item: String, val qty: Int). Son objet compagnon contient les constantes MAX_QTY = 10 et PREFIX = "ORD", un compteur privé pour le numéro de la prochaine commande, le total partagé en lecture seule totalItems et le count calculé des commandes créées. Le bloc init exige une quantité comprise entre 1 et MAX_QTY avec le message quantity must be 1-10 (construit à partir de la constante), attribue ensuite à la commande son identifiant ORD-001, ORD-002, ... et ajoute sa quantité à totalItems. label() renvoie ORD-001 tea x2.

Le code fourni affiche max per order: 10, puis lit les lignes tea 2 et affiche le libellé ou le message d’erreur, et enfin orders: 2, items: 5. Les commandes refusées ne consomment pas de numéro.

Votre code doit se trouver dans Order.kt. Main.kt contient le code fourni pour les entrées et sorties et ne peut pas être modifié.

Essayez vous-même

fun main() {
    // Code d'entrée/sortie fourni : le garder tel quel
    val input = generateSequence(::readLine).toList()
    println("max per order: ${Order.MAX_QTY}")
    for (line in input) {
        val (item, qty) = line.split(" ")
        try {
            println(Order(item, qty.toInt()).label())
        } catch (e: IllegalArgumentException) {
            println(e.message)
        }
    }
    println("orders: ${Order.count}, items: ${Order.totalItems}")
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Playground Kotlin