Objets compagnons
Fait partie de la section Programmation orientée objet du Journey Kotlin de Coddy. Leçon 13 sur 57.
Certains membres appartiennent à une classe dans son ensemble plutôt qu’à une seule instance. Kotlin les place dans un companion object à l’intérieur de la classe, et vous les appelez via le nom de la classe :
class Temperature(val celsius: Double) {
companion object {
fun fromFahrenheit(f: Double) = Temperature((f - 32) * 5 / 9)
}
}À l’intérieur de main :
val boiling = Temperature.fromFahrenheit(212.0)
println(boiling.celsius)Résultat :
100.0fromFahrenheit est une fonction fabrique : une fonction qui crée des instances. Contrairement à un constructeur, elle possède un nom descriptif et peut renvoyer null au lieu d’un objet. Avec un private constructor, la fabrique est le seul point d’accès ; elle peut donc d’abord vérifier et nettoyer l’entrée :
class Username private constructor(val text: String) {
companion object {
fun of(raw: String): Username? {
val clean = raw.trim().lowercase()
return if (clean.length in 3..12) Username(clean) else null
}
}
}Dans main :
println(Username.of(" Ada_L ")?.text)
println(Username.of("x")?.text)
// Username("x") // erreur : le constructeur est privéSortie :
ada_l
nullL’objet compagnon appartient à la classe, il peut donc appeler le constructeur privé, et le code propre à la classe utilise les membres du compagnon sans préfixe. Ici, chaque billet prend le nombre suivant d’un compteur partagé par tous les billets :
class Ticket(val holder: String) {
val number = nextNumber++
companion object {
private var nextNumber = 1
val issued: Int
get() = nextNumber - 1
}
}À l’intérieur de main :
val a = Ticket("Ada")
val b = Ticket("Bo")
println("${a.holder} #${a.number}, ${b.holder} #${b.number}")
println("issued: ${Ticket.issued}")Sortie :
Ada #1, Bo #2
issued: 2Kotlin n’a pas de mot-clé static. Les membres du compagnon jouent ce rôle : une seule copie pour toute la classe, accessible avec ClassName.member. Comme tout objet, le compagnon est créé une seule fois, lorsque la classe est utilisée pour la première fois. Placez-y ce qui ne dépend pas d’une instance, comme les fabriques et les compteurs partagés ; tout ce qui lit les données d’une instance reste un membre normal.
class User private constructor(val name: String) {
fun greet() = "hi $name" // nécessite une instance : user.greet()
companion object {
fun guest() = User("guest") // appartient à la classe : User.guest()
}
}Défi
FacileComplétez la classe Coupon. Son constructeur est privé, les coupons sont donc créés par la fabrique Coupon.create(code, percent) dans l’objet compagnon. Elle renvoie null sauf si le code comporte de 4 à 10 caractères constitués de lettres majuscules et de chiffres, et si le pourcentage est compris entre 1 et 90. L’objet compagnon compte également les coupons qu’il a créés dans created, que le code externe peut lire, mais pas modifier. apply(price) renvoie le prix diminué de la remise, arrondi à l’entier inférieur (price * (100 - percent) / 100).
Le code fourni lit des lignes SAVE10 10 200 (code, pourcentage, prix). Il affiche SAVE10: 180 ou invalid coupon SAVE10, puis enfin created: suivi du nombre.
Votre code doit être placé dans Coupon.kt. Main.kt contient le code fourni pour les entrées et les 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()
for (line in input) {
val (code, percent, price) = line.split(" ")
val coupon = Coupon.create(code, percent.toInt())
if (coupon == null) println("invalid coupon $code") else println("${coupon.code}: ${coupon.apply(price.toInt())}")
}
println("created: ${Coupon.created}")
}
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
1Classes et objets
Travailler avec des fichiersDéfinir des classesConstructeurs primairesBlocs init et validationConstructeurs secondairesRécapitulatif - Carte de bibliothèque4Héritage
Classes ouvertes et sous-classesRedéfinition des membressuper et constructeursClasses abstraitesRécapitulatif – Annuaire du personnel2Propriétés et encapsulation
Accesseurs personnalisésModificateurs de visibilitéSetters privéslazy et lateinitRécapitulatif - Compte bancaire5Interfaces
Déclarer des interfacesMéthodes par défautInterfaces multiplesInterfaces en tant que typesRécapitulatif - Méthodes de paiement8Génériques
Fonctions génériquesClasses génériquesContraintes de typeVariance avec in et outRécapitulatif - File de priorité11Projet : Gestion de bibliothèque
Livres et membresEmprunter des livresEntraînez-vous par vous-même : Playground Kotlin