Funkcje rozszerzające
Część sekcji Programowanie obiektowe ścieżki Kotlin w Coddy. Lekcja 30 z 57.
Funkcja rozszerzająca dodaje funkcję do istniejącego typu bez zmiany kodu źródłowego tego typu. Jej nazwa jest zapisywana po typie odbiorcy, a wewnątrz niej this odnosi się do odbiorcy, ale można je też pominąć:
fun String.shout() = uppercase() + "!"
fun Int.isEven() = this % 2 == 0Wewnątrz main:
println("hello".shout())
println(7.isEven())
println(listOf(1, 2, 3, 4).count { it.isEven() })Wynik:
HELLO!
false
2Rozszerzenia działają także na własnych klasach, a właściwości rozszerzające dodają właściwości obliczane. Rozszerzenie nie może dodawać przechowywanego stanu i ma dostęp tylko do publicznych składowych swojego odbiorcy:
class Temperature(val celsius: Double)
val Temperature.fahrenheit: Double
get() = celsius * 9 / 5 + 32
fun Temperature.describe() = "$celsius C is $fahrenheit F"Wewnątrz main:
println(Temperature(100.0).describe())Wynik:
100.0 C is 212.0 FRozszerzenia są rozstrzygane statycznie: typ zadeklarowany wyrażenia wybiera rozszerzenie podczas kompilacji programu, a nie klasa obiektu. To główna różnica w porównaniu z przesłoniętą składową:
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"Wewnątrz main:
val s: Shape = Circle()
println(s.member())
println(s.ext())Wynik:
circle member
shape extensionJeśli klasa ma już składową o takim samym podpisie, składowa zawsze wygrywa. Używaj składowych w przypadku zachowań, które należą do typu i mogą być nadpisywane; używaj rozszerzeń w przypadku pomocniczych funkcji dodawanych z zewnątrz, takich jak formatowanie dla klasy, której nie jesteś właścicielem:
class Robot {
fun greet() = "member greet"
}
fun Robot.greet() = "extension greet"
fun Robot.wave() = "extension wave"Wewnątrz main:
val r = Robot()
println(r.greet())
println(r.wave())Wynik:
member greet
extension waveWyzwanie
ŁatwyMoney(cents) jest dostarczone w pliku Money.kt. Napisz dla niego rozszerzenia w pliku MoneyExtensions.kt: właściwości rozszerzające Int.dollars i Int.cents, które zamieniają liczbę na Money (12.dollars to 1200 centów), Money.format(), które zwraca $12.50 (lub -$3.05 dla kwot ujemnych), List<Money>.total(), które zwraca sumę jako Money, oraz Money.split(parts), które dzieli kwotę na parts części różniących się o najwyżej jeden cent, przy czym większe części są na początku.
Dostarczony kod odczytuje wiersze 12 dollars lub 50 cents oraz ostatni wiersz zawierający liczbę części. Wyświetla każdą kwotę, total: $12.50 i split 3: $4.17 $4.17 $4.16.
Twój kod umieść w plikach MoneyExtensions.kt i Money.kt. Plik Main.kt zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
fun main() {
// Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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() })
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasKonstruktory główneBloki init i walidacjaKonstruktory dodatkowePodsumowanie — karta biblioteczna4Dziedziczenie
Klasy otwarte i podklasyNadpisywanie składowychsuper i konstruktoryKlasy abstrakcyjnePodsumowanie – katalog pracowników7Klasy specjalne
Klasy danychKlasy wyliczenioweHierarchie zapieczętowaneequals, hashCode, toStringPodsumowanie — śledzenie zamówień10Wzorce projektowe, część 2
Delegowanie za pomocą byWzorzec dekoratoraWzorzec budowniczegoWzorzec stanu2Właściwości i hermetyzacja
Własne akcesoryModyfikatory widocznościPrywatne setterylazy i lateinitPowtórka – konto bankowe5Interfejsy
Deklarowanie interfejsówMetody domyślneWiele interfejsówInterfejsy jako typyPowtórzenie – metody płatności8Typy generyczne
Funkcje generyczneKlasy generyczneOgraniczenia typówKowariancja i kontrawariancja: in i outPodsumowanie — kolejka priorytetowa11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książek3Obiekty i obiekty towarzyszące
Deklaracje obiektówObiekty towarzysząceStałe z constWyrażenia obiektowePowtórzenie — kasa biletowa6Polimorfizm
Dynamiczne wiązanieSprawdzanie typów i inteligentne rzutowaniewhen z typamiFunkcje rozszerzającePodsumowanie – opiekun zooPoćwicz samodzielnie: Edytor online Kotlin