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 2 - Proměnné, typový systém a parsování v Kotlinu

Z minulé lekce Kotlin kurzu, Úvod do jazyka Kotlin, platformy a IntelliJ, již umíme pracovat s IntelliJ a vytvořit si nový projekt pro spouštění Kotlin kódu.

Dnes se v Kotlin tutoriálu podíváme na tzv. typový systém, ukážeme si základní datové typy a práci s proměnnými. Také dojde řeč na rozdíl mezi klíčovými slovy var a val.

Proměnné

Než začneme řešit datové typy, pojďme se shodnout na tom, co je to proměnná (programátoři nám teď jistě odpustí zbytečné vysvětlování). Určitě znáte proměnnou z matematiky (např. x), do které jsme si mohli uložit nějakou hodnotu, nejčastěji číslo. Proměnná v informatice je naprosto totéž, je to místo v paměti počítače, kam si můžeme uložit nějaká data (jméno uživatele, aktuální čas nebo databázi článků). Toto místo má podle typu proměnné také vyhrazenou určitou velikost, kterou proměnná nesmí přesáhnout (např. číslo nesmí být větší než 2 147 483 647).

Proměnná má vždy nějaký datový typ. Může to být číslo, znak, text a podobně, záleží na tom, k čemu chceme proměnnou používat. Většinou musíme před prací s proměnnou tuto proměnnou nejdříve tzv. deklarovat čili říci jazyku, jak se bude jmenovat a jakého datového typu bude (jaký v ní bude obsah). Jazyk ji v paměti založí a teprve potom s ní můžeme pracovat. Podle datového typu proměnné si ji jazyk dokáže z paměti načíst, modifikovat, případně ji v paměti založit. O každém datovém typu jazyk ví, kolik v paměti zabírá místa a jak s tímto kusem paměti bude pracovat.

Typový systém

Existují dva základní typové systémy: statický a dynamický:

  • Dynamický typový systém nás plně odstiňuje od toho, že proměnná má vůbec nějaký datový typ. Ona ho samozřejmě vnitřně má, ale jazyk to nedává najevo. Dynamické typování jde mnohdy tak daleko, že proměnné nemusíme ani deklarovat. Jakmile do nějaké proměnné něco uložíme a jazyk zjistí, že proměnná nebyla nikdy deklarována, sám ji založí. Do téže proměnné můžeme ukládat text, potom objekt uživatele a potom desetinné číslo. Jazyk se s tím sám vypořádá a vnitřně automaticky změní datový typ. V těchto jazycích jde vývoj rychleji díky menšímu množství kódu. Zástupci jsou např. PHP nebo Ruby.
  • Statický typový systém naopak striktně vyžaduje definovat typ proměnné a tento typ je dále neměnný. Jakmile proměnnou jednou deklarujeme, není možné její datový typ změnit. Jakmile se do textového řetězce pokusíme uložit objekt uživatele, dostaneme vynadáno.

Kotlin je staticky typovaný jazyk, všechny proměnné tedy mají pevně daný datový typ. Ten ale často nemusíme udávat, neboť kompilátor vhodný datový typ sám doplní, pokud jej explicitně neurčíme. Obrovskou výhodou je, že nám kompilátor před spuštěním zkontroluje, zda všechny datové typy sedí. Dynamické typování sice vypadá jako výhodné, ale zdrojový kód není možné automaticky kontrolovat. Když někde např. očekáváme objekt uživatele, ale místo toho nám tam přijde desetinné číslo, odhalí se chyba až za běhu a interpret program shodí. Naopak Kotlin nám nedovolí program ani zkompilovat a na chybu nás upozorní (to je další výhoda kompilace).

Pojďme si nyní něco naprogramovat, ať si nabyté znalosti trochu osvojíme. S teorií budeme pokračovat až příště. Řekněme si nyní tři základní datové typy:

  • celá čísla – Int,
  • desetinná čísla – Double,
  • textový řetězec – String.

Práce s proměnnými

Zkusíme si nadeklarovat celočíselnou proměnnou a, dosadit do ní číslo 56 a obsah této proměnné vypsat. Založme si nový projekt s názvem Promenne. Nezapomeňte, že celý kód musíme vložit do funkce main(). V příkladu níže si ji ještě uvedeme, u těch dalších si ji už vždy připište sami:

Metodu main() nám může pomoci vygenerovat IntelliJ. Stačí napsat text main a stisknout klávesu Enter nebo Tab.

fun main(args: Array<String>) {
    var a: Int

    a = 56

    println(a)
}

Když program spustíme, uvidíme v konzoli číslo 56:

56

První příkaz nám nadeklaruje novou proměnnou a datového typu Int. Proměnná tedy bude sloužit k ukládání celých čísel. Druhý příkaz provádí přiřazení do proměnné, slouží k tomu operátor "rovná se" (=). Poslední příkaz již dobře známe, slouží k výpisu do konzole.

Kód bychom mohli zkrátit a deklaraci s inicializací proměnné provést v jednom kroku:

var a = 56
println(a)

Kompilátor sám pozná, že hodnotě 56 nejlépe odpovídá datový typ Int a na pozadí ho doplní. Typ bychom samozřejmě mohli i explicitně uvést:

var a: Int = 56

V Kotlinu se ovšem většinou datové typy takto nespecifikují.

Ukažme si ještě, jak by náš program vypadal s proměnnou pro desetinná čísla:

var a = 56.6
println(a)

Je to téměř stejné jako s celočíselnou proměnnou. Jako desetinný oddělovač používáme tečku (.).

var vs. val

Zatím jsme se u proměnných seznámili se slůvkem var, které právě proměnnou označuje. Častěji se však v Kotlin světě setkáme s podobným slůvkem val. To slouží k deklaraci neměnné proměnné, kterou není dále možné měnit. Protože v běžném programování je takových hodnot většina, používá se primárně val. K var se uchýlíme pouze v případě, že plánujeme hodnotu proměnné dále měnit. Slovo val nám zajistí, že má proměnná vždy konstantní hodnotu, kterou jsme jí poprvé přiřadili, a nikdy se nám nestane, že by nějaká část kódu omylem měnila hodnotu našich proměnných.

Funkčnost val si můžeme snadno ověřit třeba takto:

val a: Int

a = 56

a = 22

Jak můžete vidět, IntelliJ zobrazí chybu, protože není možné měnit hodnotu val proměnné.

Chyba při změně val proměnné v Kotlinu - Základní konstrukce jazyka Kotlin

Program Papoušek

Minulý program byl poněkud nudný, zkusme proto nějak reagovat na vstup od uživatele. Napíšeme program Papoušek, který bude dvakrát opakovat to, co uživatel napsal. Něco načítat z konzole jsme ještě nezkoušeli, ale je to velmi jednoduché. Slouží k tomu funkce readLine(), která nám vrátí textový řetězec z konzole. Zkusme si napsat následující kód:

println("Ahoj, jsem virtuální papoušek Lóra, rád opakuji!")
println("Napiš něco: ")

var vstup: String
vstup = readLine()!!

var vystup: String
vystup = vstup + ", " + vstup + "!"

println(vystup)

To už je trochu zábavnější :) První dva řádky kódu jsou jasné, dále deklarujeme textový řetězec vstup. Do vstup se přiřadí hodnota z funkce readLine(), tedy to, co uživatel zadal. Vykřičníky za metodou zatím neřešte, slouží k tomu, abychom nemuseli vstup ověřovat. Pro výstup si pro názornost zakládáme další proměnnou typu textový řetězec. Zajímavé je, jak jsme do proměnné vystup přiřadili hodnotu. Využili jsme k tomu tzv. konkatenaci (spojování) řetězců. Pomocí operátoru + totiž můžeme spojit několik textových řetězců do jednoho a je jedno, zda je řetězec v proměnné, nebo je explicitně zadán v uvozovkách ve zdroj. kódu. Do proměnné tedy přiřadíme vstup, dále čárku, znovu vstup a poté vykřičník. Proměnnou vypíšeme a skončíme.

Ahoj, jsem virtuální papoušek Lóra, rád opakuji!
Napiš něco:
Nazdar ptáku
Nazdar ptáku, Nazdar ptáku!

Do proměnné můžeme přiřazovat již v její deklaraci, můžeme tedy nahradit:

var vstup: String
vstup = readLine()!!

za:

val vstup = readLine()!!

Program by bylo možné zkrátit v mnoha ohledech ještě více. Obecně je ale lepší používat více proměnných a dodržovat přehlednost než psát co nejkratší kód a po měsíci zapomenout, jak vlastně funguje.

Program Zdvojnásobovač

Zdvojnásobovač si vyžádá na vstupu číslo a to poté zdvojnásobí a vypíše. S dosavadními znalostmi bychom napsali asi něco takového:

println("Zadejte číslo k zdvojnásobení:")
var a: Int = readLine()!!
a = a * 2
println(a)

Všimněme si zdvojnásobení čísla a, které jsme provedli pomocí přiřazení. Kotlin nám nyní vyhubuje a podtrhne řádek, ve kterém se snažíme hodnotu z konzole dostat do proměnné typu Int. Narážíme na typovou kontrolu, konkrétně nám readLine() vrací typ String a my se ho snažíme uložit do typu Int. Cokoli přijde z textové konzole, je vždy text. A to i když zadáme číslo. Abychom získali skutečně číslo, budeme ho muset tzv. naparsovat.

Parsování

Parsováním se myslí převod z textové podoby na nějaký specifický typ, např. číslo. Často totiž od uživatele či nějaké služby dostaneme data jako String, ale pro další výpočty potřebujeme například Int nebo Double. Parsování je v Kotlinu velmi jednoduché, má však zásadní „ale“, o kterém si krátce povíme níže. Budeme-li chtít naparsovat např. typ Int z typu String, budeme postupovat takto:

val a = "343".toInt()

Vidíme, že datový typ String nabízí metodu toInt() k přetypovávání na typ Int. Metoda bere jako parametr textový řetězec a vrátí řetězec převedený na celé číslo. O dalších podobných metodách si povíme podrobněji dále v kurzu. Využijme nyní této znalosti v našem programu:

println("Zadejte číslo k zdvojnásobení:")
val vstup = readLine()!!
var a = vstup.toInt() // případně Double
a = a * 2
println(a)

Obdobně budeme postupovat v případě Double:

var parsedDouble = "34.2".toDouble()

Parsování se samozřejmě nemusí povést. Představte si, že v textu bude místo čísla např. "slovo". Pokud si zkusíme naparsovat cokoli, co není číslo, uvidíme, že nám aplikace spadne. IntelliJ vypíše v konzoli červeným výrazným textem Exception in thread "main" java.lang.NumberFormatException: For input string: "slovo".

Chyba při parsování v Kotlinu - Základní konstrukce jazyka Kotlin

Jednoduchá kalkulačka

Ještě jsme nepracovali s desetinnými čísly, zkusme si proto napsat slibovanou kalkulačku. Bude velmi jednoduchá, na vstup přijdou dvě čísla, program poté vypíše výsledky pro sčítání, odčítání, násobení a dělení.

println("Vítejte v kalkulačce")
println("Zadejte první číslo:")
val a = readLine()!!.toDouble()
println("Zadejte druhé číslo:")
val b = readLine()!!.toDouble()
val soucet = a + b
val rozdil = a - b
val soucin = a * b
val podil = a / b
println("Součet: ${soucet}")
println("Rozdíl: ${rozdil}")
println("Součin: ${soucin}")
println("Podíl: ${podil}")
println("Děkuji za použití kalkulačky.")

Výstup:

Vítejte v kalkulačce
Zadejte první číslo:
3.14
Zadejte druhé číslo:
2.72
Součet: 5.86
Rozdíl: 0.41999999999999993
Součin: 8.5408
Podíl: 1.1544117647058822
Děkuji za použití kalkulačky.

Všimněte si dvou věcí. Zaprvé jsme zjednodušili parsování z konzole tak, abychom nepotřebovali stringovou proměnnou, protože bychom ji poté již stejně nepoužili. Zadruhé na konci programu potřebujeme vypsat čísla a před nimi ještě doprovodný text. Abychom mohli do textu vložit obsah našich proměnných, „obalíme“ naše čísla (či cokoli jiného) do ${}. Tato praktika se nazývá String Templating (řetězcové šablonování) a na pozadí zkrátka dojde k vyhodnocení výrazu v ${}. Klidně bychom zde mohli číslo ještě třeba vynásobit či dále upravit.

Možná vás napadlo, že vypsat součet dvou proměnných by se dalo i takto jednoduše:

println("Součet ${a + b}")

Potom máte pravdu :)

V následujícím cvičení, Řešené úlohy k 1.-2. lekci Kotlinu, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 128x (21.09 kB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin

 

Předchozí článek
Úvod do jazyka Kotlin, platformy a IntelliJ
Všechny články v sekci
Základní konstrukce jazyka Kotlin
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 1.-2. lekci Kotlinu
Článek pro vás napsal Samuel Kodytek
Avatar
Uživatelské hodnocení:
117 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