Lekce 2 - Proměnné, typový systém a parsování v Kotlin
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 mi teď jistě odpustí zbytečné vysvětlování).
Určitě znáte z matematiky proměnnou (např. x
), do které jsme
si mohli uložit nějakou hodnotu, nejčastěji číslo. Proměnná je v
informatice naprosto to samé, 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 ji chceme 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 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 nebyla nikdy deklarována, sám ji založí. Do té samé proměnné můžeme ukládat text, potom objekt uživatele a potom desetinné číslo. Jazyk se s tím sám popere a vnitřně automaticky mě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živatel, 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, kompilátor vhodný datový typ sám doplní, pokud jej neurčíme explicitně. 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 a když někde očekáváme objekt uživatel a přijde nám tam místo toho 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žte 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 ji vždy připište již 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 pro 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:
{KOTLIN_CONSOLE}
var a = 56
println(a)
{/KOTLIN_CONSOLE}
Kompilátor sám pozná, že hodnotě 56
nejlépe odpovídá
datový typ Int
a na pozadí ho doplní. Samozřejmě bychom typ
mohli i explicitně uvést:
var a: Int = 56
V Kotlin 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:
{KOTLIN_CONSOLE}
var a = 56.6
println(a)
{/KOTLIN_CONSOLE}
Je to téměř stejné jako s celočíselným. 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 ale ve světě Kotlin potkáme podobné
slůvko val
. To slouží pro 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
a
var
pouze v případě, že plánujete hodnotu proměnné dále
měnit. 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é.
Program Papoušek
Minulý program byl poněkud nudný, zkusme nějak reagovat na vstup od
uživatele. Napíšeme program papoušek, který bude dvakrát opakovat to, co
uživatel napsal. Ještě jsme nezkoušeli z konzole nic načítat, 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:
{KOTLIN_CONSOLE}
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)
{/KOTLIN_CONSOLE}
To už je trochu zábavnější První dva řádky 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 do vystup
přiřadíme, tam
využíváme tzv. konkatenace (spojování) řetězců. Pomocí operátoru
+
totiž můžeme spojit několik textových řetězců do jednoho
a je jedno, jestli 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 šel zkrátit ještě více v mnoha ohledech. 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 vůbec funguje.
Program zdvojnásobovač
Zdvojnásobovač si vyžádá na vstupu číslo a to poté zdvojnásobí a vypíše. Asi bychom s dosavadními znalostmi napsali něco takového:
println("Zadejte číslo k zdvojnásobení:") var a: Int = readLine()!! a = a * 2 println(a)
Všimněte 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í
String
a my se ho snažíme uložit do Int
. Cokoli
přijde z textové konzole je vždy text a to i když zadáme číslo. Budeme ho
potřebovat 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 dostanete data
jako String
, ale vy pro další výpočty potřebujete například
Int
nebo Double
. Parsování je v Kotlin velmi
jednoduché, má ale zásadní "ale", o kterém si krátce povíme níže. Pokud
budeme chtít naparsovat např. Int
ze String
, budeme
postupovat takto:
val a = "343".toInt()
Vidíme, že datový typ String
nabízí metodu
toInt()
na 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žijeme této znalosti v našem programu:
{KOTLIN_CONSOLE}
println("Zadejte číslo k zdvojnásobení:")
val vstup = readLine()!!
var a = vstup.toInt() // případně Double
a = a * 2
println(a)
{/KOTLIN_CONSOLE}
Obdobně budete postupovat v případě Double
:
var parsedDouble = "34.2".toDouble()
Parsování se samozřejmě nemusí povést. Představte si, že bude v textu
místo čísla např. "slovo"
. Pokud si zkusíte parsovat
cokoliv, co není číslo, tak uvidíte, že vá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"
.
Jednoduchá kalkulačka
Ještě jsme nepracovali s desetinnými čísly, zkusme si 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í.
{KOTLIN_CONSOLE}
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.")
{/KOTLIN_CONSOLE}
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 stejně
již poté nepoužili. Zadruhé na konci programu potřebujeme vypsat čísla a
před nimi ještě doprovodný text. Abychom mohli do text vložit obsah našich
proměnných, "obalíme" naše čísla (či cokoliv 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ě byste zde mohli číslo ještě třeba vynásobit či
dále upravit.
Možná vás napadlo, že vypsat součet 2 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 Kotlin, 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 114x (21.09 kB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin