Kurs Kotlin dla programistów 5.2: Ogólne

Te ćwiczenia są częścią kursu Kotlin dla programistów. Skorzystaj z tego kursu, jeśli będziesz wykonywać kolejno kilka ćwiczeń z programowania. W zależności od Twojej wiedzy możesz mieć dostęp do niektórych sekcji. Ten kurs jest przeznaczony dla programistów, którzy znają język zorientowany na obiekty i chcą się dowiedzieć Kotlina.

Wstęp

Dzięki nim dowiesz się, jak wyglądają zajęcia ogólne, funkcje i metody w Kotlinie.

Lekcje nie obejmują jednej przykładowej aplikacji, ale mają one na celu pogłębianie wiedzy. Między innymi należy jednak pamiętać o zależności od siebie. W połączeniu wiele z przykładów wykorzystuje motyw akwariowy. A jeśli chcesz zobaczyć pełne informacje o oceanarium, zapoznaj się z kursem Kotlin Bootcamp for Programmers (Ukocity) na platformie Udacity.

Co musisz wiedzieć

  • Składnia funkcji, klas i metod Kotlin
  • Jak utworzyć nową klasę w IntelliJ IDEA i uruchomić program

Czego się nauczysz

  • Praca z klasami, metodami i funkcjami ogólnymi

Jakie zadania wykonasz:

  • Utwórz klasę ogólną i dodaj ograniczenia
  • Tworzenie typów in i out
  • Tworzenie ogólnych funkcji, metod i rozszerzeń

Wprowadzenie do ogólnych informacji

Kotlin, podobnie jak wiele innych języków programowania, ma typy ogólne. Typ ogólny pozwala ustawić zajęcia ogólnie, dzięki czemu klasa jest znacznie bardziej elastyczna.

Załóżmy, że implementujesz klasę MyList, która zawiera listę elementów. Jeśli nie chcesz używać ogólnych danych, musisz wdrożyć nową wersję MyList dla każdego typu: jedną dla Double, jedną dla String, jedną dla Fish. Korzystając z opcji ogólnych, możesz uczynić listę ogólną, więc będzie ona obsługiwać dowolny typ obiektu. To jak symbol wieloznaczny, który pasuje do wielu typów.

Aby zdefiniować typ ogólny, umieść nazwę T w nawiasach kątowych <T> za nazwą klasy. (Możesz użyć innej litery lub dłuższej nazwy, ale konwencja typu ogólnego to T).

class MyList<T> {
    fun get(pos: Int): T {
        TODO("implement")
    }
    fun addItem(item: T) {}
}

Możesz odnieść się do obiektu T, tak jakby był to typ normalny. Zwracany typ get() to T, a parametr addItem() to T. Oczywiście listy ogólne są bardzo przydatne, więc klasa List jest wbudowana w Kotlin.

Krok 1. Utwórz hierarchię typów

W tym kroku utworzysz klasy do użycia w następnym kroku. Wcześniejsze seminaria były omówione podczas wcześniejszego ćwiczenia z programowania, ale oto krótkie omówienie.

  1. Aby zachować przejrzystość przykładu, utwórz nowy pakiet w sekcji src i nazwij go generics.
  2. W pakiecie generic utwórz nowy plik Aquarium.kt. Dzięki temu możesz zmienić definicje przy użyciu tych samych nazw, nie powodując konfliktów, więc reszta kodu ćwiczenia pozostanie w tym pliku.
  3. Utwórz hierarchię typów typów wody. Zacznij od ustawienia klasy WaterSupply jako klasy open, aby móc ją przypisać do innych klas.
  4. Dodaj wartość logiczną var (needsProcessing). Spowoduje to automatyczne utworzenie zmiennej właściwości wraz z metodą getter i seter.
  5. Utwórz podkategorię TapWater, która przedłuża WaterSupply i przekazuje true dla needsProcessing, ponieważ woda do kranu zawiera dodatki, które są szkodliwe dla ryb.
  6. W funkcji TapWater zdefiniuj funkcję o nazwie addChemicalCleaners(), która ustawia needsProcessing na false po oczyszczeniu wody. Właściwość needsProcessing może zostać ustawiona jako TapWater, ponieważ domyślnie ma wartość public i jest dostępna dla podklas. Oto kompletny kod.
package generics

open class WaterSupply(var needsProcessing: Boolean)

class TapWater : WaterSupply(true) {
   fun addChemicalCleaners() {
       needsProcessing = false
   }
}
  1. Utwórz jeszcze 2 podgrupy klasy WaterSupply o nazwie FishStoreWater i LakeWater. FishStoreWater nie wymaga przetwarzania, ale LakeWater należy filtrować za pomocą metody filter(). Po zakończeniu filtrowania nie trzeba go ponownie przetwarzać, więc ustaw filter() na needsProcessing = false.
class FishStoreWater : WaterSupply(false)

class LakeWater : WaterSupply(true) {
   fun filter() {
       needsProcessing = false
   }
}

Jeśli potrzebujesz dodatkowych informacji, zapoznaj się z poprzednią lekcją dotyczącą dziedziczenia w Kotlinie.

Krok 2. Utwórz zajęcia ogólne

W tym kroku zmodyfikujesz klasę Aquarium, aby obsługiwała różne rodzaje źródeł wody.

  1. W klasie Aquarium.kt zdefiniuj klasę Aquarium, a w nawiasach po jej nazwie wpisz <T>.
  2. Dodaj stałą właściwość waterSupply typu T do Aquarium.
class Aquarium<T>(val waterSupply: T)
  1. Napisz funkcję o nazwie genericsExample(). Nie jest to element klasy, więc może znajdować się na najwyższym poziomie pliku, na przykład funkcji main() czy definicji klas. Utwórz w funkcji Aquarium i przekaż mu parametr WaterSupply. Parametr waterSupply jest parametrem ogólnym, dlatego musisz określić typ w nawiasach kątowych <>.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
}
  1. W lokalizacji genericsExample() Twój kod może uzyskać dostęp do oceanarium waterSupply. Ze względu na typ TapWater możesz wywołać polecenie addChemicalCleaners() bez przesyłania.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. Podczas tworzenia obiektu Aquarium możesz usunąć nawiasy kątowe i odstępy między nimi, bo Kotlin ma wpływ na typ. Nie ma więc powodu, żeby powtarzać TapWater przy tworzeniu instancji. Ten typ może być wywnioskowany przez argument Aquarium. Nadal będzie miał wartość Aquarium typu TapWater.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. Aby sprawdzić, co się dzieje, wydrukuj tekst needsProcessing przed nawiązaniem połączenia z numerem addChemicalCleaners() i po nim. Poniżej znajduje się ukończona funkcja.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
    aquarium.waterSupply.addChemicalCleaners()
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}
  1. Dodaj funkcję main(), by wywołać genericsExample(), uruchom program i obserwuj wyniki.
fun main() {
    genericsExample()
}
⇒ water needs processing: true
water needs processing: false

Krok 3. Określ bardziej szczegółowo

Ogólnie rzecz biorąc, można W tym kroku sprecyzujesz, co może zawierać klasa Aquarium.

  1. W genericsExample() utwórz Aquarium, przekazując ciąg znaków waterSupply, a następnie wydrukuj oceanarium waterSupply.
fun genericsExample() {
    val aquarium2 = Aquarium("string")
    println(aquarium2.waterSupply)
}
  1. Uruchom program, aby sprawdzić wyniki.
⇒ string

W efekcie przekazany jest ciąg, bo Aquarium nie może nałożyć żadnych ograniczeń na T.typ dowolnego typu, w tym String.

  1. W genericsExample() utwórz kolejny Aquarium, przekazując null dla waterSupply. Jeśli waterSupply ma wartość NULL, wydrukuj wartość "waterSupply is null".
fun genericsExample() {
    val aquarium3 = Aquarium(null)
    if (aquarium3.waterSupply == null) {
        println("waterSupply is null")
    }
}
  1. Uruchom program i obserwuj wyniki.
⇒ waterSupply is null

Po co dawać null podczas tworzenia obiektu Aquarium? Jest to możliwe, ponieważ domyślnie T to skrót od wartości null (Any?), czyli typ u góry hierarchii typów. Poniżej znajduje się tekst.

class Aquarium<T: Any?>(val waterSupply: T)
  1. Aby nie zezwalać na przekazywanie wartości null, zmień typ T na Any, usuwając ? za Any.
class Aquarium<T: Any>(val waterSupply: T)

W tym kontekście zasada Any jest nazywana ogólnym ograniczeniem. Oznacza to, że każdy typ T można przekazać, o ile jest określony jako null.

  1. Musisz jedynie upewnić się, że w przypadku właściwości T można przekazać tylko klasę WaterSupply (lub jedną z jej podkategorii). Zastąp Any wartością WaterSupply, aby zdefiniować bardziej ogólne ograniczenie.
class Aquarium<T: WaterSupply>(val waterSupply: T)

Krok 4. Dodaj kolejne sprawdzanie

Na tym etapie poznasz funkcję check(), która pomoże Ci upewnić się, że kod działa zgodnie z oczekiwaniami. Funkcja check() jest standardową biblioteką w Kotlinie. Działa jako potwierdzenie i zwraca IllegalStateException, jeśli argument ma wartość false.

  1. Dodaj metodę addWater() do klasy Aquarium, aby dodać wodę, oraz właściwość check(), która zapewnia, że nie będzie trzeba najpierw jej 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 (prawda), check() zgłasza wyjątek.

  1. W systemie genericsExample() dodaj kod, by utworzyć Aquarium z LakeWater, a potem dodaj do niego wodę.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.addWater()
}
  1. Uruchom program, a otrzymasz wyjątek, ponieważ woda musi zostać najpierw odfiltrowana.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first
        at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)
  1. Dodaj wywołanie, aby filtrować wodę przed dodaniem jej do urządzenia Aquarium. Od tej pory nie ma wyjątków.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.waterSupply.filter()
    aquarium4.addWater()
}
⇒ adding water from generics.LakeWater@880ec60

W tym artykule znajdziesz podstawowe informacje o generałach. Poniżej znajdziesz więcej informacji na ten temat. Zastanów się jednak, jak zadeklarować klasę ogólne i jak z niej korzystać.

W tym zadaniu poznasz typy rozpoczęcia i zakończenia związane z ogólnymi zasadami. Typ in można przekazać tylko do klasy, a nie zwrócić. Typ out to typ, który może zostać zwrócony tylko z klasy.

W klasie Aquarium możesz zobaczyć, że typ ogólny jest zwracany tylko podczas pobierania usługi waterSupply. Nie ma żadnych metod, które przyjmowały wartość typu T jako parametr (z wyjątkiem definiowania jej w konstruktorze). Kotlin umożliwia definiowanie typów out dokładnie w tym przypadku i ustala dodatkowe informacje o tym, gdzie można ich bezpiecznie używać. I podobnie możesz definiować typy in w przypadku typów ogólnych, które kiedykolwiek są przekazywane do metod, a nie zwracane. Dzięki temu Kotlin może przeprowadzić dodatkową kontrolę bezpieczeństwa kodu.

Typy in i out to dyrektywy systemu Kotlin. Wyjaśnienie całego systemu typów jest poza zakresem tego kursu (jest on dość skomplikowany). Jednak kompilator może oznaczyć typy, które nie są odpowiednio oznaczone in i out, więc musisz o nich wiedzieć.

Krok 1. Zdefiniuj typ typu wyjściowego

  1. W klasie Aquarium zmień T: WaterSupply na typ out.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    ...
}
  1. W tym samym pliku poza klasą zadeklaruj funkcję addItemTo(), która oczekuje Aquarium z WaterSupply.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")
  1. Zadzwoń pod numer addItemTo() (genericsExample()) i uruchom program.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    addItemTo(aquarium)
}
⇒ item added

Kotlin może zagwarantować, że addItemTo() nie będzie wykonywać żadnych działań niebezpiecznych w typie WaterSupply, ponieważ zadeklarowano go jako typ out.

  1. Jeśli usuniesz słowo kluczowe out, kompilator wywoła błąd podczas wywoływania metody addItemTo(), ponieważ Kotlin nie może zagwarantować, że nie wykonujesz niczego, co jest niebezpieczne dla tego typu.

Krok 2. Określ typ reklamy

Typ in jest podobny do typu out, ale w przypadku typów ogólnych, które nigdy nie są przekazywane do funkcji, nie zostały zwrócone. Jeśli spróbujesz zwrócić typ in, wystąpi błąd kompilatora. W tym przykładzie określisz typ in jako część interfejsu.

  1. W witrynie Aquarium.kt zdefiniuj interfejs Cleaner, który używa ogólnego typu T, który jest ograniczony do WaterSupply. Ponieważ jest używany tylko jako argument funkcji clean(), możesz ustawić go jako parametr in.
interface Cleaner<in T: WaterSupply> {
    fun clean(waterSupply: T)
}
  1. Aby użyć interfejsu Cleaner, utwórz klasę TapWaterCleaner, która implementuje Cleaner do czyszczenia TapWater, dodając środki chemiczne.
class TapWaterCleaner : Cleaner<TapWater> {
    override fun clean(waterSupply: TapWater) =   waterSupply.addChemicalCleaners()
}
  1. W klasie Aquarium zaktualizuj addWater(), aby pobierał Cleaner typu T, i wyczyść go przed dodaniem.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    fun addWater(cleaner: Cleaner<T>) {
        if (waterSupply.needsProcessing) {
            cleaner.clean(waterSupply)
        }
        println("water added")
    }
}
  1. Zmień przykładowy kod genericsExample(), aby TapWaterCleaner, Aquarium z TapWater, a następnie dodaj trochę wody, używając środka czyszczącego. W razie potrzeby spowoduje to użycie czyszczenia.
fun genericsExample() {
    val cleaner = TapWaterCleaner()
    val aquarium = Aquarium(TapWater())
    aquarium.addWater(cleaner)
}

Kotlin użyje informacji typu in i out, aby upewnić się, że kod wykorzystuje ogólne dane. Typy Out i in są łatwe do zapamiętania: typy out można przekazywać na zewnątrz jako wartości zwrotne, a typy in – do wewnątrz jako argumenty.

Jeśli chcesz dowiedzieć się więcej o rodzajach i typach błędów, zapoznaj się z dokumentacją na ich temat.

W ramach tego zadania dowiesz się więcej o funkcjach ogólnych i o tym, kiedy ich używać. Zazwyczaj utworzenie funkcji ogólnej jest dobrym pomysłem za każdym razem, gdy funkcja przyjmuje argument klasy klasy ogólnego.

Krok 1. Utwórz funkcję ogólną

  1. W icsics/Aquarium.kt utwórz funkcję isWaterClean(), która zajmuje Aquarium. Musisz określić ogólny typ parametru. Jedną z opcji jest użycie WaterSupply.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
   println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}

Oznacza to jednak, że element Aquarium musi mieć parametr typu out, aby można było go wywołać. Czasami użycie właściwości out lub in jest zbyt restrykcyjne, bo zarówno w danych wejściowych, jak i w wynikach musisz użyć typu. Wymagania dotyczące funkcji out możesz usunąć, ustawiając tę funkcję jako ogólną.

  1. Aby funkcja była ogólna, stosuj nawiasy kątowe po słowie kluczowym fun, podając typ ogólny T i wszystkie ograniczenia, w tym przypadku WaterSupply. Zmień typ ograniczenia Aquarium, który ma być ograniczony przez T zamiast WaterSupply.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
   println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}

T to parametr typu isWaterClean() używany do określania ogólnego typu akwarium. Ten schemat jest bardzo powszechny i dobrze jest poświęcić chwilę na zapoznanie się z jego treścią.

  1. Wywołaj funkcję isWaterClean(), określając typ w nawiasach kątowych tuż po nazwie funkcji i przed nawiasami.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean<TapWater>(aquarium)
}
  1. Ze względu na skojarzenie typu z argumentem aquarium typ nie jest potrzebny, więc go usuń. Uruchom program i obserwuj wyniki.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean(aquarium)
}
⇒ aquarium water is clean: false

Krok 2. Utwórz metodę ogólną o zregenerowanym typie

Możesz też używać funkcji ogólnych w metodach, nawet w zajęciach z własnym typem ogólnym. W tym kroku dodasz do metody Aquarium metodę ogólną, która sprawdza, czy ma ona typ WaterSupply.

  1. W klasie Aquarium zadeklaruj metodę hasWaterSupplyOfType(), która przyjmuje parametr ogólny R (T jest już używany), ograniczony do WaterSupply i zwraca true, jeśli waterSupply ma typ R. To jest funkcja zadeklarowana wcześniej, ale w klasie Aquarium.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
  1. Zauważ, że ostatnie R jest podkreślone na czerwono. Najedź na niego kursorem, aby zobaczyć, co jest nie tak.
  2. Aby przeprowadzić weryfikację is, musisz poinformować Kotlin, że typ jest zreformowany lub prawdziwy i można go użyć w funkcji. Aby to zrobić, wpisz inline przed słowem kluczowym fun, a reified przed typem ogólnym R.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R

Gdy typ zostanie zmodyfikowany, możesz go używać jako zwykłego typu – jest to rzeczywisty typ po wbudowaniu. Oznacza to, że za pomocą typu możesz sprawdzić is.

Jeśli nie użyjesz tu typu reified, typ nie będzie „prawdziwy” dostatecznie, by Kotlin zezwolić na sprawdzanie is. Dzieje się tak, ponieważ typy niezrealizowane są dostępne tylko w momencie kompilacji i nie mogą być używane w czasie działania programu. Więcej informacji znajdziesz w następnej sekcji.

  1. Jako typ podaj TapWater. Podobnie jak w przypadku funkcji ogólnych, należy wywoływać ogólne metody, stosując nawiasy kątowe z typem po nazwie funkcji. Uruchom program i obserwuj wyniki.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())   // true
}
⇒ true

Krok 3. Ustaw rozszerzenia

Tych typów wartości możesz też używać w przypadku zwykłych funkcji i rozszerzeń.

  1. Poza klasą Aquarium zdefiniuj w WaterSupply funkcję rozszerzenia o nazwie isOfType(), która sprawdza, czy przekazane zdarzenie WaterSupply jest określonego typu, na przykład TapWater.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T
  1. Wywołaj funkcję rozszerzenia tak samo jak metoda.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.waterSupply.isOfType<TapWater>())  
}
⇒ true

Przy użyciu funkcji rozszerzenia nie ma znaczenia, jaki jest typ Aquarium (Aquarium, TowerTank lub inna podklasa), o ile chodzi o atrybut Aquarium. Składnia projekcji-gwiazdki to wygodny sposób określania różnych dopasowań. Korzystając z projekcji gwiazd, Kotlin zadba również o to, aby nie wykonywać żadnych niebezpiecznych działań.

  1. Aby użyć odwzorowania gwiazd, umieść <*> po Aquarium. Przenieś funkcję hasWaterSupplyOfType() jako funkcję rozszerzenia, ponieważ nie jest ona częścią podstawowego interfejsu API usługi Aquarium.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R
  1. Zmień połączenie na hasWaterSupplyOfType() i uruchom program.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())
}
⇒ true

W poprzednim przykładzie konieczne było oznaczenie typu ogólnego jako reified i umieszczenie funkcji inline, ponieważ Kotlin musi wiedzieć o nich w czasie działania, a nie tylko w czasie kompilacji.

Kotlin korzysta z wszystkich typów ogólnych w czasie kompilowania. Dzięki temu kompilator upewni się, że wszystko jest bezpieczne. W czasie działania usuwane są wszystkie typy ogólne, dlatego poprzedni komunikat o błędzie dotyczący sprawdzania wykasowanego typu jest usuwany.

Okazuje się, że kompilator może utworzyć prawidłowy kod bez zachowania typów ogólnych do czasu działania. Oznacza to jednak, że czasami wykonujesz jakąś czynność, na przykład is sprawdza ogólny typ treści, a kompilator nie jest w stanie jej obsłużyć. Z tego właśnie powodu Kotlin dodał prawdziwe i zaktualizowane typy.

Więcej informacji o zreformowanych typach i wymazywaniu typów znajdziesz w dokumentacji Kotlin.

Ta lekcja dotyczy ogólnych zagadnień, które są ważne, ponieważ wymagają większej elastyczności i łatwiejszego wykorzystania kodu.

  • Utwórz klasy ogólne, aby zwiększyć elastyczność kodu.
  • Dodaj ograniczenia ogólne, aby ograniczyć typy używane w przypadku ogólnych zasad.
  • Używaj typów in i out z typami ogólnymi, aby zwiększyć dokładność sprawdzania typu ograniczającego przekazywanie do klas lub zwracanie ich z zajęć.
  • Twórz ogólne funkcje i metody do pracy z typami ogólnymi. Przykład:
    fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... }
  • Używaj ogólnych funkcji rozszerzeń, aby dodawać do klasy funkcje spoza zestawu podstawowego.
  • Usunięte typy czasami są konieczne z powodu wymazania typu. W porównaniu z typami ogólnymi do czasu działania zachowują się typy kontrolowane.
  • Użyj funkcji check(), aby sprawdzić, czy kod działa zgodnie z oczekiwaniami. Przykład:
    check(!waterSupply.needsProcessing) { "water supply needs processing first" }

Dokumentacja Kotlin

Jeśli chcesz dowiedzieć się więcej na dowolny temat dotyczący tego kursu lub nie wiesz, co zrobić, wejdź na https://kotlinlang.org.

Samouczki Kotlin

Na stronie https://try.kotlinlang.org znajdziesz szczegółowe samouczki o nazwie Kotlin Koans, internetowe narzędzie do tłumaczenia, a także kompletny zestaw dokumentacji referencyjnej z przykładami.

Kurs Udacity

Kurs Udacity na ten temat znajdziesz na kursie Kotlin dla programistów.

IntelLIJ IDEA

Dokumentację IntelliJ IDEA znajdziesz na stronie JetBrains.

Ta sekcja zawiera listę możliwych zadań domowych dla uczniów, którzy pracują w ramach tego ćwiczenia w ramach kursu prowadzonego przez nauczyciela. To nauczyciel może wykonać te czynności:

  • W razie potrzeby przypisz zadanie domowe.
  • Poinformuj uczniów, jak przesyłać zadania domowe.
  • Oceń projekty domowe.

Nauczyciele mogą wykorzystać te sugestie tak długo, jak chcą lub chcą, i mogą przypisać dowolne zadanie domowe.

Jeśli samodzielnie wykonujesz te ćwiczenia z programowania, możesz sprawdzić swoją wiedzę w tych zadaniach domowych.

Odpowiedz na te pytania.

Pytanie 1

Która z tych konwencji ma typową nazwę?

<Gen>

<Generic>

<T>

<X>

Pytanie 2

Ograniczenie typów dopuszczalnych w przypadku typów ogólnych nazywa się:

▢ ogólne ograniczenie

▢ ograniczenie ogólne

▢ ogólny limit typów

Pytanie 3

Oznacza to:

▢ Obliczono rzeczywisty wpływ wykonania obiektu.

▢ Dla zajęć został ustawiony indeks z ograniczonym dostępem.

▢ Parametr ogólnego typu został zmieniony na prawdziwy.

▢ Zdalny wskaźnik błędu został aktywowany.

Przejdź do następnej lekcji: 6. Manipulowanie funkcjami

Omówienie kursu, w tym linki do innych ćwiczeń z programowania, znajdziesz w artykule "Kotlin Bootcamp for Programmers: Witamy na kursie."