Menu
Coddy logo textTech

Fonctions d’extension

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

Une fonction d’extension ajoute une fonction à un type existant sans modifier le code source du type. Son nom s’écrit après le type récepteur et, à l’intérieur, this fait référence au récepteur, ce qui peut également être omis :

fun String.shout() = uppercase() + "!"
fun Int.isEven() = this % 2 == 0

À l’intérieur de main :

println("hello".shout())
println(7.isEven())
println(listOf(1, 2, 3, 4).count { it.isEven() })

Résultat :

HELLO!
false
2

Les extensions fonctionnent également sur vos propres classes, et les propriétés d’extension ajoutent des propriétés calculées. Une extension ne peut pas ajouter d’état stocké et n’accède qu’aux membres publics de son récepteur :

class Temperature(val celsius: Double)

val Temperature.fahrenheit: Double
    get() = celsius * 9 / 5 + 32

fun Temperature.describe() = "$celsius C is $fahrenheit F"

À l’intérieur de main :

println(Temperature(100.0).describe())

Sortie :

100.0 C is 212.0 F

Les extensions sont résolues statiquement : le type déclaré de l’expression détermine l’extension lors de la compilation du programme, et non la classe de l’objet. C’est la principale différence avec un membre redéfini :

open class Shape {
    open fun member() = "shape member"
}
class Circle : Shape() {
    override fun member() = "circle member"
}

fun Shape.ext() = "shape extension"
fun Circle.ext() = "circle extension"

À l’intérieur de main :

val s: Shape = Circle()
println(s.member())
println(s.ext())

Sortie :

circle member
shape extension

Lorsque la classe possède déjà un membre avec la même signature, le membre l’emporte toujours. Utilisez les membres pour les comportements qui appartiennent au type et peuvent être redéfinis ; utilisez les extensions pour les assistants ajoutés de l’extérieur, comme le formatage d’une classe dont vous n’êtes pas propriétaire :

class Robot {
    fun greet() = "member greet"
}

fun Robot.greet() = "extension greet"
fun Robot.wave() = "extension wave"

Dans main :

val r = Robot()
println(r.greet())
println(r.wave())

Sortie :

member greet
extension wave
challenge icon

Défi

Facile

Money(cents) est fourni dans Money.kt. Écrivez des extensions pour celui-ci dans MoneyExtensions.kt : les propriétés d’extension Int.dollars et Int.cents, qui transforment un nombre en Money (12.dollars correspond à 1200 cents), Money.format(), qui renvoie $12.50 (ou -$3.05 pour les montants négatifs), List<Money>.total(), qui renvoie la somme sous forme de Money, et Money.split(parts), qui répartit le montant en parts montants différant d’au plus un centime, les plus grands en premier.

Le code fourni lit des lignes 12 dollars ou 50 cents, ainsi qu’une dernière ligne contenant le nombre de parts. Il affiche chaque montant, total: $12.50 et split 3: $4.17 $4.17 $4.16.

Votre code doit être placé dans MoneyExtensions.kt et Money.kt. Main.kt contient le code fourni d’entrée/sortie 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()
    val amounts = input.dropLast(1).map { line ->
        val (n, unit) = line.split(" ")
        if (unit == "dollars") n.toInt().dollars else n.toInt().cents
    }
    for (m in amounts) println(m.format())
    val total = amounts.total()
    println("total: ${total.format()}")
    val parts = input.last().toInt()
    println("split $parts: " + total.split(parts).joinToString(" ") { it.format() })
}
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