Menu
CoddyTech

Funzioni di estensione

Fa parte della sezione Programmazione orientata agli oggetti del percorso Kotlin di Coddy. Lezione 30 di 57.

Una funzione di estensione aggiunge una funzione a un tipo esistente senza modificarne il codice sorgente. Il suo nome viene scritto dopo il tipo ricevente e, al suo interno, this fa riferimento al ricevente, che può anche essere omesso:

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

All'interno di main:

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

Output:

HELLO!
false
2

Le estensioni funzionano anche con le tue classi, e le proprietà di estensione aggiungono proprietà calcolate. Un'estensione non può aggiungere uno stato memorizzato e può accedere solo ai membri pubblici del suo ricevente:

class Temperature(val celsius: Double)

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

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

All'interno di main:

println(Temperature(100.0).describe())

Output:

100.0 C is 212.0 F

Le estensioni vengono risolte staticamente: è il tipo dichiarato dell’espressione a determinare l’estensione in fase di compilazione del programma, non la classe dell’oggetto. Questa è la differenza principale rispetto a un membro sottoposto a override:

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"

All'interno di main:

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

Output:

circle member
shape extension

Quando la classe ha già un membro con la stessa firma, il membro ha sempre la precedenza. Usa i membri per i comportamenti che appartengono al tipo e che possono essere sovrascritti; usa le estensioni per gli helper aggiunti dall’esterno, ad esempio per formattare una classe che non possiedi:

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

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

Dentro main:

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

Output:

member greet
extension wave
challenge icon

Sfida

Facile

Money(cents) è fornito in Money.kt. Scrivi le estensioni in MoneyExtensions.kt: le proprietà di estensione Int.dollars e Int.cents, che trasformano un numero in Money (12.dollars corrisponde a 1200 centesimi), Money.format(), che restituisce $12.50 (o -$3.05 per gli importi negativi), List<Money>.total(), che restituisce la somma come Money, e Money.split(parts), che suddivide l'importo in parts importi che differiscono al massimo di un centesimo, con quelli più grandi per primi.

Il codice fornito legge righe come 12 dollars o 50 cents e un'ultima riga con il numero di parti. Stampa ogni importo, total: $12.50 e split 3: $4.17 $4.17 $4.16.

Il tuo codice va inserito in MoneyExtensions.kt e Money.kt. Main.kt contiene il codice fornito per l'input/output e non può essere modificato.

Provalo tu

fun main() {
    // Codice di input/output fornito: lascialo così com'è
    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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Playground Kotlin