Menu
Coddy logo textTech

Erweiterungsfunktionen

Teil des Abschnitts Objektorientierte Programmierung der Kotlin-Journey von Coddy. Lektion 30 von 57.

Eine Erweiterungsfunktion fügt einem vorhandenen Typ eine Funktion hinzu, ohne den Quellcode des Typs zu ändern. Ihr Name wird nach dem Empfängertyp geschrieben, und innerhalb der Funktion verweist this auf den Empfänger; es kann auch weggelassen werden:

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

Innerhalb von main:

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

Ausgabe:

HELLO!
false
2

Erweiterungen funktionieren auch für deine eigenen Klassen, und Erweiterungseigenschaften fügen berechnete Eigenschaften hinzu. Eine Erweiterung kann keinen gespeicherten Zustand hinzufügen und greift nur auf die öffentlichen Member ihres Empfängers zu:

class Temperature(val celsius: Double)

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

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

Innerhalb von main:

println(Temperature(100.0).describe())

Ausgabe:

100.0 C is 212.0 F

Erweiterungen werden statisch aufgelöst: Der deklarierte Typ des Ausdrucks bestimmt beim Kompilieren die Erweiterung, nicht die Klasse des Objekts. Dies ist der Hauptunterschied zu einem überschriebenen Member:

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"

Innerhalb von main:

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

Ausgabe:

circle member
shape extension

Wenn die Klasse bereits ein Mitglied mit derselben Signatur hat, hat das Mitglied immer Vorrang. Verwende Mitglieder für Verhalten, das zum Typ gehört und überschrieben werden kann; verwende Erweiterungen für Hilfsfunktionen, die von außen hinzugefügt werden, beispielsweise zur Formatierung einer Klasse, die dir nicht gehört:

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

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

Innerhalb von main:

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

Ausgabe:

member greet
extension wave
challenge icon

Aufgabe

Einfach

Money(cents) wird in Money.kt bereitgestellt. Schreibe dafür Erweiterungen in MoneyExtensions.kt: die Erweiterungseigenschaften Int.dollars und Int.cents, die eine Zahl in Money umwandeln (12.dollars entspricht 1200 Cent), Money.format(), das $12.50 zurückgibt (oder -$3.05 für negative Beträge), List<Money>.total(), das die Summe als Money zurückgibt, und Money.split(parts), das den Betrag in parts Teilbeträge aufteilt, die sich um höchstens einen Cent unterscheiden, wobei die größeren zuerst kommen.

Der bereitgestellte Code liest Zeilen wie 12 dollars oder 50 cents sowie eine letzte Zeile mit der Anzahl der Teile ein. Er gibt jeden Betrag, total: $12.50 und split 3: $4.17 $4.17 $4.16 aus.

Dein Code gehört in MoneyExtensions.kt und Money.kt. Main.kt enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

fun main() {
    // Gelieferter Ein-/Ausgabecode: belasse ihn wie er ist
    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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Kotlin-Playground