NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 3 - Typový systém podruhé - Datové typy v Kotlinu

V předešlém cvičení, Řešené úlohy k 1.-2. lekci Kotlinu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

Nyní se podíváme více zblízka na datové typy a vysvětlíme si, kdy který použít. Dnešní lekce bude hodně teoretická, ale o to praktičtější bude ta příští. Na konci lekce si vytvoříme několik jednoduchých ukázek.

Kotlin nám poskytuje spoustu datových typů k ukládání různých dat. Java a další jazyky kvůli optimalizaci výkonu rozlišovaly, zda je typ tzv. primitivní, nebo složitý, a podle toho s ním poté pracovaly. Tento mechanismus sice ušetřil nějaký výkon, ale nebyl intuitivní. Kotlin žádné takové rozlišení nedělá a i jednotlivá čísla se vnitřně ukládají úplně stejně jako komplexní objekty.

Celočíselné datové typy

Podívejme se nyní na tabulku všech vestavěných celočíselných datových typů v Kotlinu. Všimněme si typu Int, který již známe z minula.

Datový typ Rozsah Velikost
Byte −128 až 127 8 bitů
Short −32768 až 32767 16 bitů
Int −2147483648 až 2147483647 32 bitů
Long −263 to 263 − 1 64 bitů

Rozsahy těchto typů si samozřejmě nemusíte pamatovat, pro celá čísla můžete jednoduše používat vždy typ Int.

Asi vás napadá otázka, proč máme tolik možných typů pro uložení čísla. Odpověď je prostá: záleží na jeho velikosti. Čím větší číslo je, tím více paměti spotřebuje. Pro věk uživatele tedy zvolíme Byte, protože se jistě nedožije více než 127 let. Představme si databázi milionu uživatelů nějakého systému. Když zvolíme místo Byte typ Int, bude databáze zabírat čtyřikrát více místa. Naopak když budeme mít funkci k výpočtu faktoriálu, rozsah typu Int nám bude stěží stačit, a proto použijeme Long.

Nad výběrem datového typu nemusíme moc přemýšlet a většinou se používá jednoduše Int. Typ se řeší pouze v případě, když jsou proměnné v nějakém poli (obecně kolekci) a je jich tedy více. Potom se vyplatí zabývat se paměťovými nároky. Tabulky sem dáváme spíše pro úplnost.

Desetinná čísla

U desetinných čísel je situace poněkud jednodušší, máme totiž na výběr pouze ze dvou datových typů. Samozřejmě se opět liší v rozsahu hodnoty, dále však ještě v přesnosti (vlastně počtu des. míst). Double má již dle názvu dvojnásobnou přesnost oproti Float.

Datový typ Rozsah Přesnost
Float +−1.4 * 10^−45 až +−3.4 * 1038 7 čísel
Double +−5.0 * 10^−324 až +−1.7 * 10308 15–16 čísel

Vzhledem k tomu, že desetinná čísla jsou v počítači uložena ve dvojkové soustavě, dochází k určité ztrátě přesnosti. Odchylka je sice téměř zanedbatelná, nicméně pokud budete programovat např. finanční systém, nepoužívejte tyto dat. typy pro uchování peněz, mohlo by dojít k malým odchylkám.

Typ Double je pro desetinná čísla výchozí, Float je tak nutné blíže specifikovat. Když do Float chceme dosadit přímo ve zdrojovém kódu, musíme použít sufix F.

val f: Float = 3.14f
val d = 2.72

Jako desetinný separátor používáme ve zdrojovém kódu vždy tečku, nehledě na to, jaké máme v operačním systému regionální nastavení.

Další vestavěné datové typy

Podívejme se na další datové typy, které nám Kotlin nabízí:

Datový typ Rozsah Velikost/přesnost
Char U+0000 až U+ffff 16 bitů
Boolean true nebo false 8 bitů
Char

Char nám reprezentuje jeden znak. Tím se liší od typu String, který reprezentuje celý řetězec hodnot Char. Znaky v Kotlinu píšeme do apostrofů:

val c: Char = 'A'

Char patří v podstatě do celočíselných proměnných (obsahuje číselný kód znaku), ale přišlo nám logičtější uvést ho zde.

Boolean

Datový typ Boolean nabývá dvou hodnot:

  • true (pravda),
  • false (nepravda).

Budeme ho používat zejména tehdy, až se dostaneme k podmínkám. Do proměnné typu Boolean lze uložit jak přímo hodnotu true/false, tak i logický výraz. Zkusme si jednoduchý příklad:

Klikni pro editaci
  • val b = false
    val vyraz = 15 > 5
    println(b)
    println(vyraz)
    
    • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

    Výstup programu:

    Konzolová aplikace
    false
    true

    Výrazy můžeme psát do závorek. To se hodí v případě, kdy jich máme např. několik. Vidíme, že výraz nabývá hodnoty true (pravda), protože 15 je opravdu větší než 5. Od výrazů je to jen krok k podmínkám, na které se podíváme příště.

    String

    Datový typ, s nímž se setkáme na každém kroku. Reprezentuje řetězec znaků či prostě jakýkoli text. My si ukážeme hlavně důležité metody, které je dobré znát nebo o nichž je potřeba vědět, že existují.

    contains(), endsWith() a startsWith()

    Můžeme se jednoduše zeptat, zda řetězec začíná, končí nebo zda obsahuje určitý podřetězec (substring). Podřetězcem myslíme část původního řetězce. Všechny tyto metody budou jako parametr brát samozřejmě podřetězec a vracet hodnoty typu Boolean (true/false). Na výstup zatím neumíme reagovat, ale pojďme si ho alespoň vypsat:

    Klikni pro editaci
    • val s = "Krokonosohroch"
      println(s.startsWith("krok"))
      println(s.endsWith("hroch"))
      println(s.contains("nos"))
      println(s.contains("roh"))
      
      • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

      Výstup programu:

      Konzolová aplikace
      false
      true
      true
      false

      Vidíme, že vše funguje podle očekávání. První výraz samozřejmě neprošel kvůli tomu, že řetězec ve skutečnosti začíná velkým písmenem.

      toUpperCase() a toLowerCase()

      Rozlišování velkých a malých písmen může být někdy na obtíž. Mnohdy se budeme potřebovat zeptat na přítomnost podřetězce tak, aby na velikosti písmen nezáleželo. Situaci můžeme vyřešit pomocí metod toUpperCase() a toLowerCase(), které vracejí řetězec ve velkých a v malých písmenech. Uveďme si reálnější příklad, než je Krokonosohroch. Budeme mít v proměnné řádek konfiguračního souboru, který psal uživatel. Jelikož se na vstupy od uživatelů nelze spolehnout, musíme se snažit eliminovat možné chyby, zde např. ohledně velkých písmen.

      Klikni pro editaci
      • var konfig = "Fullscreen shaDows autosave"
        konfig = konfig.toLowerCase()
        println("Poběží hra ve fullscreenu?")
        println(konfig.contains("fullscreen"))
        println("Budou zapnuté stíny?")
        println(konfig.contains("shadows"))
        println("Přeje si hráč vypnout zvuk?")
        println(konfig.contains("nosound"))
        println("Přeje si hráč hru automaticky ukládat?")
        println(konfig.contains("autosave"))
        
        • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

        Výstup programu:

        Konzolová aplikace
        Poběží hra ve fullscreenu?
        true
        Budou zapnuté stíny?
        true
        Přeje si hráč vypnout zvuk?
        false
        Přeje si hráč hru automaticky ukládat?
        true

        Vidíme, že jsme schopni zjistit přítomnost jednotlivých slov v řetězci tak, že si nejprve řetězec převedeme celý na malá písmena (nebo na velká) a potom kontrolujeme přítomnost slova jen malými (nebo velkými) písmeny. Takto by mimochodem mohlo opravdu vypadat jednoduché zpracování nějakého konfiguračního skriptu.

        replace()

        Asi nejdůležitější metodou na typu String je nahrazení určité jeho části jiným textem. Jako parametry zadáme dva podřetězce: jeden, který chceme nahrazovat, a druhý, kterým chceme původní nahradit. Metoda vrátí nový String, ve kterém proběhlo nahrazení. Když daný podřetězec metoda nenajde, vrátí původní řetězec. Zkusme si to:

        var s = "Java je nejlepší!"
        s = s.replace("Java", "Kotlin")
        println(s)

        Výstup programu:

        Konzolová aplikace
        Kotlin je nejlepší!

        trim()

        Další nástrahou mohou být mezery a obecně všechny tzv. bílé znaky, které nejsou vidět, ale mohou nám v aplikaci způsobovat problémy. Obecně je dobré trimovat všechny vstupy od uživatele. Zkuste si v následující aplikaci před číslo a za číslo zadat několik mezer, které trim() odstraní. Odstraňují se vždy bílé znaky kolem řetězce, nikoli uvnitř:

        Klikni pro editaci
        • println("Zadej číslo:")
          val s = readLine()!!
          println("Zadal jsi text: $s")
          println("Text po funkci trim: " + s.trim())
          val a = s.trim().toInt()
          println("Převedl jsem zadaný text na číslo parsováním, zadal jsi: $a")
          
          • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

          Zkuste program spustit a zadat před číslo několik mezer:

          Zadej číslo:        10
          Zadal jsi text:        10
          Text po funkci trim: 10
          Převedl jsem zadaný text na číslo parsováním, zadal jsi: 10

          Řetězcové šablony

          Řetězcové šablony, někdy označované jako tzv. interpolace řetězců, jsme si již zmiňovali. Pokud chceme do řetězce v Kotlinu na určitá místa vložit nějaké proměnné, zapíšeme je přímo do řetězce pomocí značek $.

          Klikni pro editaci
          • val a = 10
            val b = 20
            val c = a + b
            println("Když sečteme $a a $b, dostaneme $c")
            
            • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

            Výstup programu:

            Konzolová aplikace
            Když sečteme 10 a 20, dostaneme 30

            Komplikovanější výrazy vkládáme ještě do složených závorek za znak dolaru jako ${a + b}. To použijeme, pokud například chceme sečíst dvě čísla a ihned tento výsledek vypsat. Když se zamyslíme, jak jinak by měl Kotlin poznat, že chceme sečíst dvě proměnné, kdybychom napsali $ pouze před jednu proměnnou?

            Takováto funkcionalita se nám často hodí při výpisu. Zkusme si rovnou i sečíst čísla přímo ve výrazu:

            Klikni pro editaci
            • val a = 10
              val b = 20
              println("Když sečteme $a a $b, dostaneme ${a + b}")
              
              • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

              Toto je velmi užitečná a přehledná cesta, jak sestavovat řetězce. Pokud chceme vypsat čísla, tak se jí nevyhneme. Pro sloučení proměnných obsahujících řetězce s jiným řetězcem můžeme použít tzv. konkatenaci (jednoduše + pro jejich spojení do jednoho řetězce).

              val jmeno = "Bill"
              val prijmeni = "Gates"
              val celeJmeno = jmeno + " " + prijmeni

              Vlastnost length

              Poslední, ale nejdůležitější vlastností (pozor, ne metodou) je length, tedy počet znaků. Vrací celé číslo, které představuje počet znaků v řetězci. Za vlastnosti nepíšeme závorky, protože nemají parametry.

              Klikni pro editaci
              • println("Zadejte vaše jméno:")
                val jmeno = readLine()!!
                println("Délka vašeho jména je: ${jmeno.length}")
                
                • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                Je toho ještě spoustu k vysvětlování a existují další datové typy, které jsme zatím neprobrali. Teorie však bylo prozatím dost.

                V následujícím kvízu, Kvíz - Proměnné a parsování v Kotlin, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


                 

                Jak se ti líbí článek?
                Před uložením hodnocení, popiš prosím autorovi, co je špatněZnaků 0 z 50-500
                Předchozí článek
                Řešené úlohy k 1.-2. lekci Kotlinu
                Všechny články v sekci
                Základní konstrukce jazyka Kotlin
                Přeskočit článek
                (nedoporučujeme)
                Kvíz - Proměnné a parsování v Kotlin
                Článek pro vás napsal Samuel Kodytek
                Avatar
                Uživatelské hodnocení:
                93 hlasů
                Autor se věnuje všem jazykům okolo JVM. Rád pomáhá lidem, kteří se zajímají o programování. Věří, že všichni mají šanci se naučit programovat, jen je potřeba prorazit tu bariéru, který se říká lenost.
                Aktivity