Kotlin Bootcamp for Programmers 2: Kotlin basics

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ę podstaw języka programowania Kotlin: typów danych, operatorów, zmiennych, struktur sterujących oraz zmiennych dopuszczających i niedopuszczających wartości null. Ten kurs jest przeznaczony dla programistów, którzy znają język obiektowy i chcą nauczyć się Kotlina.

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ć

  • Jak utworzyć projekt w IntelliJ IDEA
  • Jak otworzyć i wykonać kod w środowisku REPL (Read-Eval-Print Loop) języka Kotlin w IntelliJ IDEA (Narzędzia > Kotlin > Kotlin REPL)

Czego się nauczysz

  • Jak używać typów danych, operatorów i zmiennych w języku Kotlin
  • Jak pracować z wartościami logicznymi i warunkami
  • Różnica między zmiennymi dopuszczającymi wartość null a zmiennymi niedopuszczającymi wartości null
  • Jak działają tablice, listy i pętle w Kotlinie

Jakie zadania wykonasz

  • Praca z REPL języka Kotlin, aby poznać jego podstawy

W tym ćwiczeniu dowiesz się więcej o operatorach i typach w języku programowania Kotlin.

Krok 1. Poznaj operatory liczbowe

  1. Otwórz IntelliJ IDEA, jeśli nie jest jeszcze otwarty.
  2. Aby otworzyć REPL języka Kotlin, kliknij Narzędzia > Kotlin > Kotlin REPL.

Podobnie jak w innych językach, w Kotlinie do oznaczania dodawania, odejmowania, mnożenia i dzielenia używa się znaków +, -, */. Kotlin obsługuje też różne typy liczb, takie jak Int, Long, DoubleFloat.

  1. Wpisz w REPL te wyrażenia: Aby zobaczyć wynik, po każdym z nich naciśnij Control+Enter (Command+Enter na komputerze Mac).
1+1
⇒ res8: kotlin.Int = 2

53-3
⇒ res9: kotlin.Int = 50

50/10
⇒ res10: kotlin.Int = 5

1.0/2.0
⇒ res11: kotlin.Double = 0.5

2.0*3.5
⇒ res12: kotlin.Double = 7.0

Pamiętaj, że wyniki operacji zachowują typy operandów, więc 1/2 = 0, ale 1.0/2.0 = 0.5.

  1. Wypróbuj kilka wyrażeń z różnymi kombinacjami liczb całkowitych i dziesiętnych.
6*50
⇒ res13: kotlin.Int = 300

6.0*50.0
⇒ res14: kotlin.Double = 300.0

6.0*50
⇒ res15: kotlin.Double = 300.0
  1. Wywoływanie niektórych metod na liczbach. W języku Kotlin liczby są traktowane jako typy proste, ale można wywoływać na nich metody tak, jakby były obiektami.
2.times(3)
⇒ res5: kotlin.Int = 6

3.5.plus(4)
⇒ res8: kotlin.Double = 7.5

2.4.div(2)
⇒ res9: kotlin.Double = 1.2

Krok 2. Ćwicz używanie typów

Kotlin nie konwertuje niejawnie typów liczbowych, więc nie możesz przypisać wartości typu short bezpośrednio do zmiennej typu long ani wartości typu Byte do zmiennej typu Int. Dzieje się tak, ponieważ niejawna konwersja liczb jest częstym źródłem błędów w programach. Zawsze możesz przypisać wartości różnych typów, używając rzutowania.

  1. Aby zobaczyć niektóre z możliwych rzutowań, zdefiniuj w REPL zmienną typu Int.
val i: Int = 6
  1. Utwórz nową zmienną, a następnie wpisz jej nazwę podaną powyżej i dodaj znak .to.
val b1 = i.to

IntelliJ IDEA wyświetli listę możliwych uzupełnień. Automatyczne uzupełnianie działa w przypadku zmiennych i obiektów dowolnego typu.

  1. Wybierz toByte() z listy, a potem wydrukuj zmienną.
val b1 = i.toByte()
println(b1)
⇒ 6
  1. Przypisz wartość Byte do zmiennych różnych typów.
val b2: Byte = 1 // OK, literals are checked statically
println(b2)
⇒ 1

val i1: Int = b2
⇒ error: type mismatch: inferred type is Byte but Int was expected

val i2: String = b2
⇒ error: type mismatch: inferred type is Byte but String was expected

val i3: Double = b2
⇒ error: type mismatch: inferred type is Byte but Double was expected
  1. W przypadku zadań, które zwróciły błędy, spróbuj je zamiast tego przesłać.
val i4: Int = b2.toInt() // OK!
println(i4)
⇒ 1

val i5: String = b2.toString()
println(i5)
⇒ 1

val i6: Double = b2.toDouble()
println(i6)
⇒ 1.0
  1. Aby długie stałe liczbowe były bardziej czytelne, Kotlin umożliwia umieszczanie w nich podkreśleń w miejscach, które uznasz za odpowiednie. Spróbuj wpisać inne stałe liczbowe.
val oneMillion = 1_000_000
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

Krok 3. Poznaj wartość typów zmiennych

Kotlin obsługuje 2 typy zmiennych: zmienne i niezmienne. Za pomocą val możesz przypisać wartość tylko raz. Jeśli spróbujesz ponownie przypisać coś do tego konta, pojawi się błąd. Za pomocą var możesz przypisać wartość, a potem zmienić ją w programie.

  1. Zdefiniuj zmienne za pomocą znaków valvar, a następnie przypisz im nowe wartości.
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
⇒ error: val cannot be reassigned

Możesz przypisać fish wartość, a następnie przypisać jej nową wartość, ponieważ jest zdefiniowana za pomocą var. Próba przypisania nowej wartości do zmiennej aquarium powoduje błąd, ponieważ jest ona zdefiniowana za pomocą funkcji val.

Typ przechowywany w zmiennej jest określany, gdy kompilator może go ustalić na podstawie kontekstu. Jeśli chcesz, możesz zawsze jawnie określić typ zmiennej, używając notacji z dwukropkiem.

  1. Zdefiniuj zmienne i określ ich typ.
var fish: Int = 12
var lakes: Double = 2.5

Gdy typ zostanie przypisany przez Ciebie lub kompilator, nie możesz go zmienić, ponieważ spowoduje to błąd.

Krok 4. Dowiedz się więcej o ciągach znaków

Ciągi znaków w Kotlinie działają podobnie jak w innych językach programowania, w których ciągi znaków są oznaczane symbolem ", a pojedyncze znaki – symbolem '. Ciągi znaków można łączyć za pomocą operatora +. Szablony ciągów znaków możesz tworzyć, łącząc je z wartościami. Nazwa $variable jest zastępowana tekstem reprezentującym wartość. Jest to tzw. interpolacja zmiennych.

  1. Utwórz szablon ciągu znaków.
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
⇒ res20: kotlin.String = I have 5 fish and 12 plants
  1. Utwórz szablon ciągu znaków z wyrażeniem. Podobnie jak w innych językach wartość może być wynikiem wyrażenia. Aby zdefiniować wyrażenie, użyj nawiasów klamrowych {}.
"I have ${numberOfFish + numberOfPlants} fish and plants"
⇒ res21: kotlin.String = I have 17 fish and plants

W tym ćwiczeniu dowiesz się więcej o wartościach logicznych i sprawdzaniu warunków w języku programowania Kotlin. Podobnie jak w innych językach, w Kotlinie występują wartości logiczne i operatory logiczne, takie jak mniejszy niż, równy, większy niż itp. (<, ==, >, !=, <=, >=).

  1. Napisz oświadczenie if/else.
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
    println("Good ratio!") 
} else {
    println("Unhealthy ratio")
}
⇒ Good ratio!
  1. Spróbuj użyć zakresu w instrukcji if. W języku Kotlin testowany warunek może też używać zakresów.
val fish = 50
if (fish in 1..100) {
    println(fish)
}
⇒ 50
  1. Napisz if z wieloma zgłoszeniami. W przypadku bardziej skomplikowanych warunków użyj operatorów logicznych i && oraz lub ||. Podobnie jak w innych językach możesz użyć else if, aby utworzyć wiele przypadków.
if (numberOfFish == 0) {
    println("Empty tank")
} else if (numberOfFish < 40) {
    println("Got fish!")
} else {
    println("That's a lot of fish!")
}
⇒ That's a lot of fish!
  1. Wypróbuj whenoświadczenie. W języku Kotlin istnieje lepszy sposób na zapisanie tej serii instrukcji if/else if/else – za pomocą instrukcji when, która jest podobna do instrukcji switch w innych językach. Warunki w instrukcji when mogą też używać zakresów.
when (numberOfFish) {
    0  -> println("Empty tank")
    in 1..39 -> println("Got fish!")
    else -> println("That's a lot of fish!")
}
⇒ That's a lot of fish!

W tym ćwiczeniu dowiesz się, czym różnią się zmienne dopuszczające wartość null od zmiennych niedopuszczających wartości null. Błędy programowania związane z wartościami null były źródłem niezliczonych błędów. Kotlin ma na celu zmniejszenie liczby błędów przez wprowadzenie zmiennych, które nie mogą mieć wartości null.

Krok 1. Dowiedz się więcej o możliwości przyjmowania wartości null

Domyślnie zmienne nie mogą mieć wartości null.

  1. Zadeklaruj Int i przypisz do niego wartość null.
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
  1. Użyj operatora znaku zapytania ? po typie, aby wskazać, że zmienna może mieć wartość null. Zadeklaruj Int? i przypisz do niego wartość null.
var marbles: Int? = null

W przypadku złożonych typów danych, takich jak lista:

  • Możesz zezwolić na to, aby elementy listy miały wartość null.
  • Możesz zezwolić na to, aby lista miała wartość null, ale jeśli nie ma wartości null, jej elementy nie mogą mieć wartości null.
  • Możesz zezwolić na to, aby lista lub elementy miały wartość null.

Listy i niektóre inne złożone typy danych omówimy w dalszej części.

Krok 2. Dowiedz się więcej o ? i ?: operatory

Możesz testować warunek null za pomocą operatora ?, co pozwoli Ci uniknąć pisania wielu instrukcji if/else.

  1. Napisz dłuższy kod, aby sprawdzić, czy zmienna fishFoodTreats nie jest równa null. Następnie zmniejsz wartość tej zmiennej.
var fishFoodTreats = 6
if (fishFoodTreats != null) {
    fishFoodTreats = fishFoodTreats.dec()
}
  1. Teraz zobacz, jak można to zapisać w Kotlinie za pomocą operatora ?.
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
  1. Możesz też łączyć testy wartości null za pomocą operatora ?:. Przyjrzyj się temu przykładowi:
fishFoodTreats = fishFoodTreats?.dec() ?: 0

Jest to skrót od „jeśli fishFoodTreats nie jest równe null, zmniejsz wartość i użyj jej; w przeciwnym razie użyj wartości po znaku ?:, czyli 0”. Jeśli wartość fishFoodTreats to null, ocena zostanie zatrzymana, a metoda dec() nie zostanie wywołana.

Uwaga dotycząca wskaźników o wartości null

Jeśli naprawdę lubisz NullPointerExceptions, Kotlin pozwala Ci ich używać. Operator potwierdzenia, że wartość nie jest zerowa, !! (podwójny wykrzyknik), przekształca dowolną wartość w typ niezerowy i zgłasza wyjątek, jeśli wartość to null.

val len = s!!.length   // throws NullPointerException if s is null

W tym ćwiczeniu dowiesz się, czym są tablice i listy, oraz poznasz różne sposoby tworzenia pętli w języku programowania Kotlin.

Krok 1. Utwórz listy

Listy są podstawowym typem w Kotlinie i są podobne do list w innych językach.

  1. Zadeklaruj listę za pomocą znaku listOf i wydrukuj ją. Tej listy nie można zmienić.
val school = listOf("mackerel", "trout", "halibut")
println(school)
⇒ [mackerel, trout, halibut]
  1. Zadeklaruj listę, którą można zmieniać za pomocą mutableListOf. Usuń element.
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
⇒ res36: kotlin.Boolean = true

Metoda remove() zwraca wartość true, gdy usunie przekazany element.

Krok 2. Tworzenie tablic

Podobnie jak w innych językach, w Kotlinie występują tablice. W przeciwieństwie do list w Kotlinie, które mają wersje modyfikowalne i niemodyfikowalne, nie ma modyfikowalnej wersji Array. Po utworzeniu tablicy jej rozmiar jest stały. Nie możesz dodawać ani usuwać elementów, z wyjątkiem kopiowania do nowej tablicy.

Reguły dotyczące używania znaków val i var są takie same w przypadku tablic jak w przypadku list.

  1. Zadeklaruj tablicę ciągów znaków za pomocą arrayOf. Aby go wydrukować, użyj narzędzia do tworzenia tablic java.util.Arrays.toString().
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
⇒ [shark, salmon, minnow]
  1. Tablica zadeklarowana za pomocą arrayOf nie ma typu powiązanego z elementami, więc możesz mieszać typy, co jest przydatne. Zadeklaruj tablicę z różnymi typami.
val mix = arrayOf("fish", 2)
  1. Możesz też deklarować tablice z jednym typem dla wszystkich elementów. Zadeklaruj tablicę liczb całkowitych za pomocą intArrayOf(). Istnieją odpowiednie konstruktory lub funkcje tworzenia instancji dla tablic innych typów.
val numbers = intArrayOf(1,2,3)
  1. Połącz 2 tablice za pomocą operatora +.
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
=> 3
  1. Wypróbuj różne kombinacje zagnieżdżonych tablic i list. Podobnie jak w innych językach możesz zagnieżdżać tablice i listy. Oznacza to, że gdy umieścisz tablicę w tablicy, otrzymasz tablicę tablic, a nie spłaszczoną tablicę zawartości obu tablic. Elementami tablicy mogą być też listy, a elementami list mogą być tablice.
val numbers = intArrayOf(1, 2, 3)
val oceans = listOf("Atlantic", "Pacific")
val oddList = listOf(numbers, oceans, "salmon")
println(oddList)
⇒ [[I@89178b4, [Atlantic, Pacific], salmon]

Pierwszy element, numbers, to Array. Jeśli nie użyjesz narzędzia do obsługi tablicy, Kotlin wydrukuje adres zamiast zawartości tablicy.

  1. Jedną z zalet języka Kotlin jest możliwość inicjowania tablic za pomocą kodu zamiast inicjowania ich wartością 0. Wypróbuj ten przykład:
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
⇒ [0, 2, 4, 6, 8]

Kod inicjowania znajduje się między nawiasami klamrowymi {}. W kodzie it odnosi się do indeksu tablicy, który zaczyna się od 0.

Krok 3. Tworzenie pętli

Gdy masz już listy i tablice, pętla przechodząca przez elementy działa zgodnie z oczekiwaniami.

  1. Utwórz tablicę. Użyj pętli for, aby wykonać iterację tablicy i wydrukować elementy.
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
    print(element + " ")
}
⇒ shark salmon minnow
  1. W Kotlinie możesz jednocześnie iterować po elementach i indeksach. Wypróbuj ten przykład:
for ((index, element) in school.withIndex()) {
    println("Item at $index is $element\n")
}
⇒ Item at 0 is shark
Item at 1 is salmon
Item at 2 is minnow
  1. Wypróbuj różne rozmiary kroków i zakresy. Możesz określić zakresy liczb lub znaków w kolejności alfabetycznej. Podobnie jak w innych językach, nie musisz zwiększać wartości o 1. Możesz cofnąć się za pomocą przycisku downTo.
for (i in 1..5) print(i)
⇒ 12345

for (i in 5 downTo 1) print(i)
⇒ 54321

for (i in 3..6 step 2) print(i)
⇒ 35

for (i in 'd'..'g') print (i)
⇒ defg
  1. Wypróbuj kilka pętli. Podobnie jak inne języki, Kotlin ma pętle while, pętle do...while oraz operatory ++--. Kotlin ma też pętle repeat.
var bubbles = 0
while (bubbles < 50) {
    bubbles++
}
println("$bubbles bubbles in the water\n")

do {
    bubbles--
} while (bubbles > 50)
println("$bubbles bubbles in the water\n")

repeat(2) {
     println("A fish is swimming")
}
⇒ 50 bubbles in the water
49 bubbles in the water
A fish is swimmingA fish is swimming

Kotlin jest bardzo podobny do innych języków, jeśli chodzi o podstawy, takie jak operatory, listy i pętle, ale istnieją pewne istotne różnice.

Te funkcje mogą działać w Kotlinie inaczej niż w innych językach:

  • Typów Kotlin nie można konwertować niejawnie – używaj rzutowania.
  • Zmienne zadeklarowane za pomocą val można przypisać tylko raz.
  • Zmienne w Kotlinie nie mogą mieć domyślnie wartości null. Użyj ?, aby umożliwić przyjmowanie wartości null przez zmienne.
  • W języku Kotlin możesz jednocześnie iterować po indeksach i elementach tablicy w pętli for.

Te konstrukcje programistyczne w języku Kotlin są podobne do tych w innych językach:

  • Tablice i listy mogą zawierać elementy jednego typu lub różnych typów.
  • Tablice i listy można zagnieżdżać.
  • Pętle możesz tworzyć za pomocą for, while, do/whilerepeat.
  • Instrukcja when to wersja instrukcji switch w języku Kotlin, ale when jest bardziej elastyczna.

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.

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óre z poniższych deklaracji tworzy niezmienną listę ciągów znaków?

▢ val school = arrayOf("shark", "salmon", "minnow")

▢ var school = arrayOf("shark", "salmon", "minnow")

▢ val school = listOf("shark", "salmon", "minnow")

▢ val school = mutableListOf("shark", "salmon", "minnow")

Pytanie 2

Jaki będzie wynik działania tego kodu?
for (i in 3..8 step 2) print(i)

▢ 345678

▢ 468

▢ 38

▢ 357

Pytanie 3

Jaki jest cel znaku zapytania w tym kodzie?
var rocks: Int? = 3

▢ Typ zmiennej rocks nie jest stały.

▢ Zmienna rocks może mieć wartość null.

▢ Zmiennej rocks nie można ustawić na wartość null.

▢ Zmienna rocks nie powinna być od razu inicjowana.

Przejdź do następnej lekcji: 3. Funkcje

Omówienie kursu, w tym linki do innych ćwiczeń, znajdziesz w artykule „Kotlin Bootcamp for Programmers: Welcome to the course” (w języku angielskim).