Te warsztaty są częścią kursu Kotlin Bootcamp for Programmers. Najwięcej korzyści przyniesie Ci ukończenie wszystkich ćwiczeń w kolejności. W zależności od swojej wiedzy możesz pominąć niektóre sekcje. Ten kurs jest przeznaczony dla programistów, którzy znają język obiektowy i chcą nauczyć się Kotlin.
Wprowadzenie
W tym laboratorium dowiesz się, czym są klasy, funkcje i metody generyczne oraz jak działają w Kotlinie.
Lekcje w tym kursie nie są powiązane z jedną przykładową aplikacją. Zostały zaprojektowane tak, aby poszerzać Twoją wiedzę, ale jednocześnie były od siebie częściowo niezależne. Dzięki temu możesz przeglądać sekcje, które już znasz. Aby je ze sobą powiązać, w wielu przykładach użyto motywu akwarium. Jeśli chcesz poznać pełną historię akwarium, zapoznaj się z kursem Kotlin Bootcamp for Programmers na platformie Udacity.
Co warto wiedzieć
- Składnia funkcji, klas i metod w języku Kotlin
- Jak utworzyć nową klasę w IntelliJ IDEA i uruchomić program
Czego się nauczysz
- Jak pracować z klasami, metodami i funkcjami ogólnymi
Jakie zadania wykonasz
- Tworzenie klasy ogólnej i dodawanie ograniczeń
- Tworzenie typów
iniout - Tworzenie funkcji, metod i funkcji rozszerzających
Wprowadzenie do typów generycznych
Kotlin, podobnie jak wiele języków programowania, ma typy ogólne. Typ ogólny umożliwia utworzenie klasy ogólnej, a tym samym zwiększenie jej elastyczności.
Załóżmy, że implementujesz klasę MyList, która zawiera listę elementów. Bez typów ogólnych musiałbyś wdrożyć nową wersję funkcji MyList dla każdego typu: jedną dla Double, jedną dla String i jedną dla Fish. Dzięki typom ogólnym możesz utworzyć listę ogólną, która może zawierać dowolny typ obiektu. To tak, jakby typ był symbolem wieloznacznym, który pasuje do wielu typów.
Aby zdefiniować typ ogólny, umieść T w nawiasach ostrych <T> po nazwie klasy. (Możesz użyć innej litery lub dłuższej nazwy, ale w przypadku typu ogólnego przyjęło się używać litery T).
class MyList<T> {
fun get(pos: Int): T {
TODO("implement")
}
fun addItem(item: T) {}
}Możesz odwoływać się do T tak, jakby był to zwykły typ. Typem zwracanym funkcji get() jest T, a parametr funkcji addItem() jest typu T. Oczywiście listy ogólne są bardzo przydatne, dlatego klasa List jest wbudowana w język Kotlin.
Krok 1. Utwórz hierarchię typów
W tym kroku utworzysz klasy, które wykorzystasz w następnym kroku. Podklasy zostały omówione w poprzednim laboratorium, ale tutaj znajdziesz krótkie podsumowanie.
- Aby przykład był bardziej przejrzysty, utwórz nowy pakiet w folderze src i nadaj mu nazwę
generics. - W pakiecie generics utwórz nowy plik
Aquarium.kt. Dzięki temu możesz ponownie zdefiniować elementy, używając tych samych nazw, bez konfliktów. Pozostała część kodu do tego laboratorium kodu znajduje się w tym pliku. - Utwórz hierarchię typów zaopatrzenia w wodę. Zacznij od utworzenia
WaterSupplyklasyopen, aby można było utworzyć jej podklasę. - Dodaj parametr logiczny
var,needsProcessing. Spowoduje to automatyczne utworzenie usługi z możliwością zmiany oraz metod get i set. - Utwórz podklasę
TapWater, która rozszerza klasęWaterSupply, i przekażtruejakoneedsProcessing, ponieważ woda z kranu zawiera dodatki, które są szkodliwe dla ryb. - W
TapWaterzdefiniuj funkcję o nazwieaddChemicalCleaners(), która po oczyszczeniu wody ustawia wartośćneedsProcessingnafalse. WłaściwośćneedsProcessingmożna ustawić z poziomu klasyTapWater, ponieważ domyślnie jest onapublici dostępna dla podklas. Oto gotowy kod.
package generics
open class WaterSupply(var needsProcessing: Boolean)
class TapWater : WaterSupply(true) {
fun addChemicalCleaners() {
needsProcessing = false
}
}- Utwórz 2 kolejne podklasy klasy
WaterSupplyo nazwachFishStoreWateriLakeWater.FishStoreWaternie wymaga przetwarzania, aleLakeWatermusi być filtrowany metodąfilter(). Po odfiltrowaniu nie trzeba go ponownie przetwarzać, więc wfilter()ustawneedsProcessing = false.
class FishStoreWater : WaterSupply(false)
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessing = false
}
}Jeśli potrzebujesz dodatkowych informacji, zapoznaj się z poprzednią lekcją o dziedziczeniu w Kotlinie.
Krok 2. Utwórz klasę ogólną
W tym kroku zmodyfikujesz klasę Aquarium, aby obsługiwała różne rodzaje źródeł wody.
- W pliku Aquarium.kt zdefiniuj klasę
Aquarium, a po nazwie klasy w nawiasach podaj<T>. - Dodaj do
Aquariumniezmienną właściwośćwaterSupplytypuT.
class Aquarium<T>(val waterSupply: T)- Napisz funkcję o nazwie
genericsExample(). Nie jest to część klasy, więc może znajdować się na najwyższym poziomie pliku, podobnie jak funkcjamain()lub definicje klas. W funkcji utwórzAquariumi przekaż do niejWaterSupply. ParametrwaterSupplyjest ogólny, więc musisz określić jego typ w nawiasach ostrych<>.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
}- W
genericsExample()Twój kod może uzyskać dostęp dowaterSupplyakwarium. Ponieważ jest to typTapWater, możesz wywołaćaddChemicalCleaners()bez rzutowania typów.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}- Podczas tworzenia obiektu
Aquariummożesz usunąć nawiasy kątowe i to, co się między nimi znajduje, ponieważ Kotlin ma wnioskowanie o typach. Dlatego podczas tworzenia instancji nie musisz wpisywaćTapWaterdwa razy. Typ można wywnioskować z argumentu funkcjiAquarium. Nadal będzie ona tworzyć obiektAquariumtypuTapWater.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}- Aby sprawdzić, co się dzieje, wydrukuj
needsProcessingprzed wywołaniem funkcjiaddChemicalCleaners()i po nim. Poniżej znajdziesz gotową funkcję.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
aquarium.waterSupply.addChemicalCleaners()
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}- Dodaj funkcję
main(), aby wywołać funkcjęgenericsExample(), a następnie uruchom program i sprawdź wynik.
fun main() {
genericsExample()
}⇒ water needs processing: true water needs processing: false
Krok 3. Uściślij pytanie
Oznacza to, że możesz przekazać prawie wszystko, a czasami jest to problem. W tym kroku Aquariumklasa staje się bardziej szczegółowa w odniesieniu do tego, co można w niej umieścić.
- W
genericsExample()utwórzAquarium, przekazując ciąg znaków dlawaterSupply, a następnie wydrukuj właściwośćwaterSupplyakwarium.
fun genericsExample() {
val aquarium2 = Aquarium("string")
println(aquarium2.waterSupply)
}- Uruchom program i sprawdź wynik.
⇒ string
Wynikiem jest przekazany ciąg znaków, ponieważ funkcja Aquarium nie nakłada żadnych ograniczeń na typ T.. Można przekazać dowolny typ, w tym String.
- W funkcji
genericsExample()utwórz kolejną funkcjęAquarium, przekazując wartośćnulljako argumentwaterSupply. JeśliwaterSupplyma wartość null, wydrukuj"waterSupply is null".
fun genericsExample() {
val aquarium3 = Aquarium(null)
if (aquarium3.waterSupply == null) {
println("waterSupply is null")
}
}- Uruchom program i sprawdź wynik.
⇒ waterSupply is null
Dlaczego podczas tworzenia Aquarium można przekazać wartość null? Jest to możliwe, ponieważ domyślnie T oznacza typ dopuszczający wartość null Any?, czyli typ na szczycie hierarchii typów. Poniższy tekst jest odpowiednikiem tego, co zostało wcześniej wpisane.
class Aquarium<T: Any?>(val waterSupply: T)- Aby nie zezwalać na przekazywanie
null, usuń?poAny, aby jawnie określić typTjakoAny.
class Aquarium<T: Any>(val waterSupply: T)W tym kontekście Any jest nazywany ogólnym ograniczeniem. Oznacza to, że w przypadku parametru T można przekazać dowolny typ, o ile nie jest to null.
- Chcesz mieć pewność, że do
Tmożna przekazać tylkoWaterSupply(lub jedną z jego podklas). Zastąp symbolAnysymbolemWaterSupply, aby zdefiniować bardziej szczegółowe ograniczenie ogólne.
class Aquarium<T: WaterSupply>(val waterSupply: T)Krok 4. Dodaj więcej sprawdzania
W tym kroku dowiesz się więcej o funkcji check(), która pomoże Ci upewnić się, że kod działa zgodnie z oczekiwaniami. Funkcja check() jest standardową funkcją biblioteczną w Kotlinie. Działa jako asercja i zwraca błąd IllegalStateException, jeśli argument ma wartość false.
- Dodaj do klasy
AquariummetodęaddWater(), aby dodać wodę, z parametremcheck(), który sprawi, że nie trzeba będzie jej wcześniej przetwarzać.
class Aquarium<T: WaterSupply>(val waterSupply: T) {
fun addWater() {
check(!waterSupply.needsProcessing) { "water supply needs processing first" }
println("adding water from $waterSupply")
}
}W tym przypadku, jeśli needsProcessing ma wartość true, funkcja check() zgłosi wyjątek.
- W
genericsExample()dodaj kod, aby utworzyćAquariumzLakeWater, a następnie dodaj do niego trochę wody.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.addWater()
}- Uruchom program, a otrzymasz wyjątek, ponieważ woda musi zostać najpierw przefiltrowana.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first
at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)- Przed dodaniem wody do
Aquariumprzefiltruj ją. Teraz, gdy uruchomisz program, nie zostanie zgłoszony żaden wyjątek.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.waterSupply.filter()
aquarium4.addWater()
}⇒ adding water from generics.LakeWater@880ec60
Powyżej znajdziesz podstawowe informacje o typach generycznych. Poniższe zadania obejmują więcej, ale ważna jest koncepcja deklarowania i używania klasy ogólnej z ograniczeniem ogólnym.
W tym ćwiczeniu dowiesz się więcej o typach wejściowych i wyjściowych z typami ogólnymi. Typ in to typ, który można tylko przekazać do klasy, a nie zwrócić. out to typ, który może być zwracany tylko przez klasę.
Spójrz na klasę Aquarium, a zobaczysz, że typ ogólny jest zwracany tylko w przypadku pobierania właściwości waterSupply. Nie ma metod, które przyjmują wartość typu T jako parametr (z wyjątkiem zdefiniowania go w konstruktorze). Kotlin umożliwia definiowanie out typów dokładnie w tym przypadku i może wywnioskować dodatkowe informacje o tym, gdzie można bezpiecznie używać typów. Podobnie możesz zdefiniować typy in dla typów ogólnych, które są tylko przekazywane do metod, a nie zwracane. Dzięki temu Kotlin może przeprowadzać dodatkowe kontrole bezpieczeństwa kodu.
Typy in i out to dyrektywy dla systemu typów języka Kotlin. Wyjaśnienie całego systemu typów wykracza poza zakres tego szkolenia (jest dość złożone). Kompilator będzie jednak odpowiednio oznaczać typy, które nie są oznaczone symbolami in i out, więc musisz o nich wiedzieć.
Krok 1. Określ typ wyjścia
- W klasie
Aquariumzmień typ elementuT: WaterSupplynaout.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
...
}- W tym samym pliku, poza klasą, zadeklaruj funkcję
addItemTo(), która oczekujeAquariumtypuWaterSupply.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")- Zadzwoń z
genericsExample()doaddItemTo()i uruchom program.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
addItemTo(aquarium)
}⇒ item added
Kotlin może zagwarantować, że addItemTo() nie wykona żadnych operacji niezgodnych z typem w przypadku typu ogólnego WaterSupply, ponieważ jest on zadeklarowany jako typ out.
- Jeśli usuniesz słowo kluczowe
out, kompilator zgłosi błąd podczas wywoływaniaaddItemTo(), ponieważ Kotlin nie może zagwarantować, że nie wykonujesz żadnych niebezpiecznych operacji na typie.
Krok 2. Określ typ wejścia
Typ in jest podobny do typu out, ale dotyczy typów ogólnych, które są tylko przekazywane do funkcji, a nie zwracane. Jeśli spróbujesz zwrócić typ in, pojawi się błąd kompilatora. W tym przykładzie zdefiniujesz in jako część interfejsu.
- W pliku Aquarium.kt zdefiniuj interfejs
Cleaner, który przyjmuje ogólny typTograniczony do typuWaterSupply. Ponieważ jest on używany tylko jako argument funkcjiclean(), możesz ustawić go jako parametrin.
interface Cleaner<in T: WaterSupply> {
fun clean(waterSupply: T)
}- Aby użyć interfejsu
Cleaner, utwórz klasęTapWaterCleaner, która implementuje interfejsCleanerdo czyszczeniaTapWaterprzez dodanie środków chemicznych.
class TapWaterCleaner : Cleaner<TapWater> {
override fun clean(waterSupply: TapWater) = waterSupply.addChemicalCleaners()
}- W klasie
AquariumzaktualizujaddWater(), aby pobraćCleanertypuT, i oczyść wodę przed jej dodaniem.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
fun addWater(cleaner: Cleaner<T>) {
if (waterSupply.needsProcessing) {
cleaner.clean(waterSupply)
}
println("water added")
}
}- Zaktualizuj przykładowy kod
genericsExample(), aby utworzyćTapWaterCleaner,AquariumzTapWater, a następnie dodaj trochę wody za pomocą środka czyszczącego. Będzie używać środka czyszczącego w razie potrzeby.
fun genericsExample() {
val cleaner = TapWaterCleaner()
val aquarium = Aquarium(TapWater())
aquarium.addWater(cleaner)
}Kotlin użyje informacji o typach in i out, aby upewnić się, że kod bezpiecznie korzysta z typów ogólnych. Out i in są łatwe do zapamiętania: typy out można przekazywać na zewnątrz jako wartości zwracane, a typy in można przekazywać do wewnątrz jako argumenty.

Jeśli chcesz dowiedzieć się więcej o problemach, które rozwiązują typy wejściowe i wyjściowe, zapoznaj się ze szczegółową dokumentacją.
Z tego zadania dowiesz się, czym są funkcje ogólne i kiedy ich używać. Zwykle warto utworzyć funkcję ogólną, gdy przyjmuje ona argument klasy, która ma typ ogólny.
Krok 1. Utwórz funkcję ogólną
- W pliku generics/Aquarium.kt utwórz funkcję
isWaterClean(), która przyjmuje argumentAquarium. Musisz określić typ ogólny parametru. Jedną z opcji jest użycieWaterSupply.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}Oznacza to jednak, że funkcja Aquarium musi mieć parametr typu out, aby można było ją wywołać. Czasami out lub in jest zbyt restrykcyjne, ponieważ musisz użyć typu zarówno dla danych wejściowych, jak i wyjściowych. Możesz usunąć wymaganie out, uogólniając funkcję.
- Aby funkcja była ogólna, umieść nawiasy kątowe po słowie kluczowym
funz ogólnym typemTi dowolnymi ograniczeniami, w tym przypadkuWaterSupply. Zmień ograniczenieAquariumnaTzamiastWaterSupply.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}T to parametr typu dla isWaterClean(), który jest używany do określania ogólnego typu akwarium. Ten wzorzec jest bardzo powszechny, więc warto poświęcić chwilę na jego przeanalizowanie.
- Wywołaj funkcję
isWaterClean(), podając typ w nawiasach ostrych bezpośrednio po nazwie funkcji i przed nawiasami.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean<TapWater>(aquarium)
}- Ze względu na wnioskowanie o typie z argumentu
aquariumtyp nie jest potrzebny, więc go usuń. Uruchom program i obserwuj dane wyjściowe.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean(aquarium)
}⇒ aquarium water is clean: false
Krok 2. Utwórz metodę ogólną z typem konkretnym
Możesz też używać funkcji ogólnych w metodach, nawet w klasach, które mają własny typ ogólny. W tym kroku dodasz do pliku Aquarium ogólną metodę, która sprawdza, czy ma on typ WaterSupply.
- W klasie
Aquariumzadeklaruj metodęhasWaterSupplyOfType(), która przyjmuje parametr ogólnyR(Tjest już używany) ograniczony doWaterSupplyi zwracatrue, jeśliwaterSupplyjest typuR. Jest to funkcja podobna do zadeklarowanej wcześniej, ale w klasieAquarium.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R- Zwróć uwagę, że ostatni znak
Rjest podkreślony na czerwono. Najedź na nią kursorem, aby zobaczyć, jaki to błąd.
- Aby wykonać sprawdzenie
is, musisz poinformować język Kotlin, że typ jest reified, czyli rzeczywisty, i może być używany w funkcji. Aby to zrobić, wstawinlineprzedfunsłowem kluczowym ireifiedprzed typem ogólnymR.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is RPo reifikacji typu możesz go używać jak zwykłego typu, ponieważ po wstawieniu jest on prawdziwym typem. Oznacza to, że możesz wykonywać sprawdzanie typu is.
Jeśli nie użyjesz tu reified, typ nie będzie wystarczająco „rzeczywisty”, aby Kotlin zezwalał na sprawdzanie is. Dzieje się tak, ponieważ typy niekonkretne są dostępne tylko w czasie kompilacji i nie mogą być używane przez program w czasie działania. Więcej informacji znajdziesz w następnej sekcji.
- Przekaż
TapWaterjako typ. Podobnie jak w przypadku wywoływania funkcji ogólnych, wywołuj metody ogólne, używając nawiasów ostrych z typem po nazwie funkcji. Uruchom program i sprawdź wynik.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>()) // true
}⇒ true
Krok 3. Utwórz funkcje rozszerzenia
Typów konkretnych możesz używać też w przypadku zwykłych funkcji i funkcji rozszerzających.
- Poza klasą
Aquariumzdefiniuj funkcję rozszerzenia w klasieWaterSupplyo nazwieisOfType(), która sprawdza, czy przekazany obiektWaterSupplyjest określonego typu, np.TapWater.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T- Wywołaj funkcję rozszerzenia tak samo jak metodę.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.waterSupply.isOfType<TapWater>())
}⇒ true
W przypadku tych funkcji rozszerzenia nie ma znaczenia, jakiego typu jest Aquarium (Aquarium, TowerTank czy inna podklasa), o ile jest to Aquarium. Składnia projekcji gwiazdowej to wygodny sposób na określenie różnych dopasowań. Gdy używasz projekcji gwiazd, Kotlin również dba o to, aby nie wykonywać żadnych niebezpiecznych działań.
- Aby użyć projekcji gwiazd, po znaku
Aquariumwpisz<*>. PrzenieśhasWaterSupplyOfType(), aby była funkcją rozszerzenia, ponieważ nie jest częścią podstawowego interfejsu APIAquarium.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R- Zmień wywołanie na
hasWaterSupplyOfType()i uruchom program.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>())
}⇒ true
W poprzednim przykładzie musieliśmy oznaczyć typ ogólny jako reified, a funkcję jako inline, ponieważ Kotlin musi znać te informacje w czasie działania programu, a nie tylko w czasie kompilacji.
Wszystkie typy ogólne są używane przez Kotlina tylko w czasie kompilacji. Dzięki temu kompilator może mieć pewność, że wszystko robisz bezpiecznie. W czasie działania programu wszystkie typy ogólne są usuwane, stąd wcześniejszy komunikat o błędzie związanym ze sprawdzaniem usuniętego typu.
Okazuje się, że kompilator może utworzyć prawidłowy kod bez przechowywania typów ogólnych do czasu wykonania. Oznacza to jednak, że czasami wykonujesz działania, np. is sprawdzasz typy ogólne, których kompilator nie obsługuje. Dlatego w języku Kotlin dodano typy reified, czyli rzeczywiste.
Więcej informacji o typach konkretnych i wymazywaniu typów znajdziesz w dokumentacji języka Kotlin.
W tej lekcji skupiliśmy się na typach ogólnych, które są ważne, ponieważ sprawiają, że kod jest bardziej elastyczny i łatwiejszy do ponownego wykorzystania.
- Twórz klasy ogólne, aby zwiększyć elastyczność kodu.
- Dodaj ogólne ograniczenia, aby ograniczyć typy używane z typami ogólnymi.
- Używaj typów
inioutz typami ogólnymi, aby zapewnić lepsze sprawdzanie typów i ograniczyć typy przekazywane do klas lub zwracane z nich. - Twórz ogólne funkcje i metody do pracy z typami ogólnymi. Na przykład:
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... } - Używaj ogólnych funkcji rozszerzających, aby dodać do klasy funkcje inne niż podstawowe.
- Typy konkretne są czasami niezbędne ze względu na usuwanie typów. Typy konkretne, w przeciwieństwie do typów ogólnych, są zachowywane w czasie działania programu.
- Użyj funkcji
check(), aby sprawdzić, czy kod działa zgodnie z oczekiwaniami. Na przykład:check(!waterSupply.needsProcessing) { "water supply needs processing first" }
Dokumentacja języka Kotlin
Jeśli chcesz uzyskać więcej informacji na dowolny temat w tym kursie lub jeśli napotkasz trudności, najlepszym punktem wyjścia będzie strona https://kotlinlang.org.
- Generics
- Ogólne ograniczenia
- Projekcje gwiazd
- Typy
Iniout - Parametry konkretne
- Wymazywanie typów
- Funkcja
check()
Samouczki dotyczące języka Kotlin
Witryna https://try.kotlinlang.org zawiera rozbudowane samouczki Kotlin Koans, internetowy interpreter i pełny zestaw dokumentacji z przykładami.
Kurs Udacity
Aby obejrzeć kurs Udacity na ten temat, zobacz Kotlin Bootcamp for Programmers (w języku angielskim).
IntelliJ IDEA
Dokumentację IntelliJ IDEA znajdziesz w witrynie JetBrains.
W tej sekcji znajdziesz listę możliwych zadań domowych dla uczniów, którzy wykonują ten moduł w ramach kursu prowadzonego przez instruktora. Nauczyciel musi:
- W razie potrzeby przypisz pracę domową.
- Poinformuj uczniów, jak przesyłać projekty.
- Oceń zadania domowe.
Instruktorzy mogą korzystać z tych sugestii w dowolnym zakresie i mogą zadawać inne zadania domowe, które uznają za odpowiednie.
Jeśli wykonujesz ten kurs samodzielnie, możesz użyć tych zadań domowych, aby sprawdzić swoją wiedzę.
Odpowiedz na te pytania
Pytanie 1
Która z poniższych opcji jest konwencją nazewnictwa typu ogólnego?
▢ <Gen>
▢ <Generic>
▢ <T>
▢ <X>
Pytanie 2
Ograniczenie typów dozwolonych w przypadku typu ogólnego nazywa się:
▢ ogólne ograniczenie,
▢ ogólne ograniczenie,
▢ rozróżnianie
▢ ogólny limit typu,
Pytanie 3
Ukonkretnione oznacza:
▢ Obliczono rzeczywisty wpływ obiektu na wykonanie.
▢ W zajęciach ustawiono indeks z ograniczonym dostępem.
▢ Parametr typu ogólnego został przekształcony w rzeczywisty typ.
▢ Wskaźnik błędu zdalnego został aktywowany.
Przejdź do następnej lekcji:
Omówienie kursu, w tym linki do innych ćwiczeń, znajdziesz w artykule „Kotlin Bootcamp for Programmers: Welcome to the course” (w języku angielskim).