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 6 - Typový systém - Null safety v Kotlinu

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

Nyní si konečně vysvětlíme koncept zvaný null safety, který je v Kotlinu velmi důležitý, a řekneme si, co znamenají všechny ty vykřičníky ve zdrojovém kódu. S několika jsme se již setkali, a ačkoli se může pro začátek jednat o složitější tematiku, bude lepší, když budeme alespoň tušit, o co se jedná.

Koncept hodnoty null

Programovací jazyky se musí nějak vypořádat se situací, kdy proměnná nemá žádnou hodnotu. S takovým problémem se často setkáváme u funkcí, které se nemusí provést korektně. Pokud se např. nepodaří načtení čísla z konzole, nemělo by být vráceno žádné číslo, ale „prázdno“. Pokud by nám Kotlin vrátil v tomto případě např. hodnotu 0 nebo -1, nepoznali bychom, zda se číslo nepodařilo načíst, nebo zda uživatel vložil právě 0 nebo -1. Za tímto účelem se zavedla speciální hodnota null, která bezpečně označí, že je proměnná prázdná.

Pokud si v Kotlinu vytvoříme standardní proměnnou, prázdnou hodnotu null do ní přiřadit nelze:

// Tento kód je chybný
var cislo = 15
cislo = null // Tento řádek vyvolá chybu

Někdo by tam totiž nemusel hodnotu null očekávat. Abychom ji mohli do proměnné přiřadit, musíme proměnnou nejdříve deklarovat jako nullovatelnou.

Nullovatelné typy

Nullovatelný typ můžeme chápat jako jakýsi box, který slouží k zabalení obyčejné proměnné. Box existuje vždy, avšak po jeho otevření buď najdeme hodnotu, nebo je prázdný. Nullovatelný typ vytvoříme tak, že za název datového typu proměnné umístíme otazník ?. Zkusme si to:

var moznaCislo: Int? = 15
moznaCislo = null

Kód se již přeložil v pořádku a proměnná moznaCislo je nyní prázdná, i když se jedná o číslo. To zní zatím dobře, že?

Nastává však problém, který mnoho ostatních programovacích jazyků nedokázalo vyřešit. S moznaCislo by nám nyní nemělo být umožněno pracovat jako s obyčejnou proměnnou. Podívejme se na následující kód:

var moznaCislo: Int? = 15
moznaCislo = null
println(moznaCislo  * 2)

Pokud bychom jej takto napsali a program by se přeložil, mohl by za běhu spadnout v případě, že by moznaCislo bylo prázdné. Nemůžeme přece vynásobit „nezadáno“ dvěma. Když si takový program zkusíme napsat, zjistíme, že nejde přeložit. Podobně by nám Kotlin vynadal i při přístupu k vlastnosti nebo metodě nullovatelného typu. Můžeme si zkusit, že kvůli výpisu délky druhého řetězce nepůjde následující kód přeložit:

var s1 = "Ahoj"
var s2: String? = "Světe"
println(s1.length)
println(s2.length)

Nejspíš tušíte, že Kotlin nepatří mezi jazyky, které by si tento problém neohlídaly :)

Null safety

Mechanismus, který již při překladu kontroluje, jak nullovatelné typy používáme, se nazývá null safety. Existuje několik způsobů, jak nullovatelnou proměnnou použít. Postupně si je vyzkoušíme.

Operátor !!

Začněme tím nejhloupějším, který jsme zatím v kurzu používali, aby toho na nás nebylo ze začátku moc. Pomocí operátoru !! můžeme Kotlin degradovat na starší jazyky, jako je např. Java, a kontrolu null safety vypnout. Pokud v proměnné zrovna nebude null, vše bude fungovat:

Klikni pro editaci
  • var moznaCislo: Int? = 15
    println(moznaCislo!!  * 2)
    
    • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

    Výsledek:

    30

    Pokud v ní ovšem prázdná hodnota bude, celá aplikace za běhu spadne s chybou:

    var moznaCislo: Int? = 15
    moznaCislo = null
    println(moznaCislo!!  * 2)

    Jelikož bychom při překladu na tuto chybu vůbec nepřišli, nebudeme řešení s !! příliš používat.

    Podmínka

    O něco chytřejší řešení je pracovat s nullovatelnými typy v podmínce na hodnotu null. Jelikož se tak vyhneme pádu programu, Kotlin nám program dovolí přeložit:

    Klikni pro editaci
    • var moznaCislo: Int? = 15
      if (moznaCislo != null)
          println(moznaCislo  * 2)
      else
          println("Číslo není zadané!")
      
      • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

      Bezpečné volání

      Určitě tušíte, že existuje lepší řešení než stále psát podmínky na null. Pomocí operátoru ?. (otazník a tečka) se buď přistoupí k dané vlastnosti, nebo se vrátí null v případě, že je proměnná prázdná.

      ?.let

      Pokud bychom použili bezpečné volání spolu s klíčovým slovem let, spustil by se kód ve složených závorkách pouze v případě, že by v proměnné byla nenullová hodnota:

      Klikni pro editaci
      • var moznaCislo: Int? = 15
        moznaCislo?.let { println(it) }
        
        • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

        Klíčové slovo it následně v bloku obsahuje tuto hodnotu. Pokud by bylo moznaCislo null, program by se přeložil a výpis by se nespustil.

        Řetězení ?.

        Tuto funkcionalitu využijeme pouze v případě, kdy se chceme zeptat přes řetěz vlastností, jako např.:

        zak?.ucitel?.nadrizeny?.jmeno

        Výraz výše vrátí buď název ředitele školy (nadřízeného učitele žáka), nebo null v případě, že je jakýkoli článek výrazu prázdný. Vyhneme se tak spoustě podmínek, musíme však pamatovat na to, že ve výsledku máme sice jeden, ale stále nullovatelný typ.

        Takto bychom mohli i bezpečně přiřadit, již bez potřeby dalších podmínek:

        zak?.ucitel?.nadrizeny?.jmeno = "Seymour Skinner"

        Elvis operátor

        Elvis operátor v Kotlinu - Základní konstrukce jazyka Kotlin

        Jak vznikl název tohoto operátoru, asi není třeba vysvětlovat :) Elvise používáme spolu s operátorem ?. a umožňuje nám zeptat se, zda je hodnota v nullovatelné proměnné null, a případně použít jinou výchozí hodnotu. Opět si to zkusme na našem příkladu:

        Klikni pro editaci
        • var moznaText: String? = "Ahoj světe"
          println(moznaText?.length ?:  0)
          
          • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

          Na pravé straně Elvis operátoru můžeme použít i return nebo vyvolání výjimek (viz další kurzy).

          V každém ze způsobů práce s hodnotou null platí, že pokud je hodnota null, další výrazy (metody) určené pro případ, kdyby hodnota null nebyla, se nespustí.

          V příští lekci, Pole v Kotlinu, se budeme věnovat polím.


           

          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 5. lekci Kotlinu
          Všechny články v sekci
          Základní konstrukce jazyka Kotlin
          Přeskočit článek
          (nedoporučujeme)
          Pole v Kotlinu
          Článek pro vás napsal Samuel Kodytek
          Avatar
          Uživatelské hodnocení:
          42 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