Menu
Coddy logo textTech

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