Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.

13. diel - Dynamic, var, null a null aware operátormi

V predchádzajúcom cvičení, Riešené úlohy k 11.-12. lekciu Dart, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

V minulej lekcii kurzu, Riešené úlohy k 11.-12. lekciu Dart , sme sa naučili pracovať s matematikou. V tejto lekcii sa zameriame na dátový typ dynamic a hodnotu null. O tej sme sa už v rámci kurzu neraz zmieňovali a dnes si ukážeme ako s ňou pracovať.

Dátový typ dynamic

Dátový typ dynamic sa hodí v situáciách, keď neviete dátový typ premennej, alebo ho nechcete určovať. V premennej tak môže byť úplne čokoľvek a kedykoľvek sa môže meniť aj jej dátový typ. V jednej chvíli tak v premennej alfa môže byť celé číslo a potom do nej priradíme reťazec:

dynamic alfa = 5;
print(alfa);
alfa = 'aaa';
print(alfa);

S takou premennú sa nám ale veľmi zle pracuje, pretože nevieme my ani IDE, čo v nej práve je uložené. Tým pádom nám IDE nevie napovedať. Ak to nie je nevyhnutné alebo vhodné, dynamic by sme používať nemali a radšej by sme ho mali nahradiť za konkrétny typ údajov.

Var

Spomenieme ešte jedno kľúčové slovo, ktorým je var. Písať dátové typy je občas zbytočné, napr. V momente, keď vieme, aký typ údajov dosadzujeme, pretože sme ho napr. Definovali už niekde vyššie. Predstavme si, že máme napr. 2 premenné, kde obe majú nejaký veľmi zložitý dátový typ:

List<List<List<List<List<List<int>>>>>> a = [];
List<List<List<List<List<List<int>>>>>> b = a;

Písať takéto typy 2x nie je zas až taký problém. Písať je už ale stále dokola je zbytočné a hlavne neprehľadné. Preto v momente, kedy je kód dostatočne prehľadný aj pochopiteľný bez opakovania dátového typu, môžeme využiť kľúčové slovo var, ktoré nám, jednoducho povedané, dosadí ten správny typ a sprehľadní tým kód.

List<List<List<List<List<List<int>>>>>> a = [];
var b = a;

Rovnako tak môžeme kľúčové slovo var použiť kdekoľvek, kde dosadzujeme literál.

var a = 1; // int
var b = 1.0; // double
var c = 'ahoj'; // String

Pozor však na situácie, kedy by sme chceli mať napr. Zoznam prvkov s ľubovoľným dátovým typom. Literál by však obsahoval len jeden typ údajov, čo var vyhodnotí ako zoznam len tohto jedného dátového typu:

var a = [1, 2, 3, 4, 5]; // List<int>
// a.add('alfa'); ... chyba

var b = [1, 2, 3, 4, 5, 'alfa']; // List<dynamic>
b.add('beta');

var c = <dynamic>[1, 2, 3, 4, 5]; // List<dynamic>
c.add('alfa');

V prvom prípade, ak by sme sa pokúsili pridať reťazec do zoznamu, nám vynadá aj statická analýza kódu, ktorá vypíše chybu "error: The argument type 'String' can not be assigned to the parameter type 'int'. (Argument_type_not_as­signable at [muj_projekt ] bin \ muj_projekt.dart: 8) ".

Všimnite si, že dátový typ prvkov zoznamu môžeme vynútiť napísaním typu do špicatých zátvoriek < > pred literál.

Užívajte teda var iba v prípadoch, ak kód nestratí na prehľadnosti a ak ste si istí, že sa vyhodnotí správne. Var by sa nám nemal pliesť s dynamic, var za nás len typ sám napíše, ale neumožňuje ho meniť a premenná sa správa rovnako, ako by sme typ napísali ručne.

Hodnota null

Niekoľkokrát sme si spomenuli hodnotu null a sľuboval som, že si ju dovysvětlíme. Čokoľvek v Dart, čo vytvoríme, ale nič do toho nepriradíte, má predvolenú hodnotu null. Hodnotu null môžeme chápať ako "nič"; dokonca až také "nič", že na nej nemôžeme volať takmer žiadne metódy alebo vlastnosti a ak to urobíme, program sa väčšinou ukončí s chybou.

Pozn .: Na null môžeme v skutočnosti volať iba metódy, ktoré má Object. Nám zatiaľ postačí vedieť, že je to napríklad metóda toString(). Tento fakt ale nič nemení na okolnostiach, že náš program môže spadnúť, čo rozhodne nechceme.

Že sa nám program naozaj ukončí s chybou si ukážeme na príklade výpise absolútnej hodnoty čísla:

int cislo; // obsahuje null
print(cislo.abs());

Výstup programu:

Konzolová aplikácia
Unhandled exception:
NoSuchMethodError: The method 'abs' was called on null.
Receiver: null
Tried calling: abs()
#0      Object._noSuchMethod (dart:core-patch/object_patch.dart:43)
#1      Object.noSuchMethod (dart:core-patch/object_patch.dart:47)
#2      main (file:///D:/git/muj_projekt/bin/muj_projekt.dart:5:15)
#3      _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)

Už z minula vieme, že hodnota null sa dá využiť aj na dobré veci (napr. Detekciu, že sme neprevzali naozaj nič, namiesto toho, aby sme hodnotu nastavili napr. Na 0), ale teraz sme tiež zistili, že je null potenciálne nebezpečný a musíme s ním zaobchádzať opatrne.

Najjednoduchšie ochranou, ktorú by ste už mali byť schopní sami zvládnuť, sú podmienky:

int cislo; // obsahuje null

if (cislo != null) {
    print(cislo.abs());
} else {
    print('Číslo neexistuje.');
}

Výstup programu:

Konzolová aplikácia
Číslo neexistuje.

Asi ale sami tušíte, že písať podmienku vždy, keď si nie sme istí, že premenná je alebo nie je null nie je moc pekné. A nie je to ani práve dvakrát prehľadné prehľadné. Našťastie sú v Dart tzv. Null-aware operátory, ktoré nám s tým veľa pomôžu.

Null-aware operátory

Operátor ??

Operátor ?? použijeme všade tam, kde chceme vrátiť hodnotu výrazu a v prípadne, že bol výraz null, potom vrátiť jeho alternatívu.

int cislo; // obsahuje null
print(cislo ?? 'Nic.');
cislo = 5;
print(cislo ?? 'Nic.');

Výstup programu:

Konzolová aplikácia
Nic.
5

Operátor ?? =

Operátor ??= použijeme všade tam, kde chceme priradiť alternatívne hodnotu, ak je pôvodná hodnota premennej null. Výsledok po použití operátora je samozrejme buď pôvodná hodnota, pokiaľ nebola null, alebo alternatíva.

int cislo; // obsahuje null
print(cislo ??= 42);
print(cislo);

int druheCislo; // obsahuje null
druheCislo ??= 666;
print(druheCislo);

Výstup programu:

Konzolová aplikácia
42
42
666

Operátor?.

Operátor ?. použijeme všade tam, kde chceme volať metódu a nie sme si istí, či nie je výraz null. Ak je null, nič sa nevykoná a výraz vracia hodnota null.

Ukážeme si náš pôvodný príklad s absolútnou hodnotou:

int cislo; // obsahuje null
print(cislo?.abs());

Výstup programu:

Konzolová aplikácia
null

Ak by sme chceli volať viac metód za sebou, treba zistiť, či je absolútna hodnota párna, použijeme operátor ?. v celom výrazu viackrát.

int cislo; // obsahuje null
print(cislo?.abs()?.isEven);
cislo = -8;
print(cislo?.abs()?.isEven);
cislo = 7;
print(cislo?.abs()?.isEven);

Výstup programu:

Konzolová aplikácia
null
true
false

Jednotlivé operátormi môžeme samozrejme kombinovať:

int cislo; // obsahuje null
print(cislo?.abs() ?? 'Číslo neexistuje.');

Výstup programu:

Konzolová aplikácia
Číslo neexistuje.

Už sme skoro u konca. Budúci lekcie, Ekosystém a konvencie Dart , je vlastne bonusová a nebude sa týkať kódu, ale ekosystému Dart programov a konvenciám v Dart.


 

Predchádzajúci článok
Riešené úlohy k 11.-12. lekciu Dart
Všetky články v sekcii
Základné konštrukcie jazyka Dart
Preskočiť článok
(neodporúčame)
Ekosystém a konvencie Dart
Článok pre vás napísal Honza Bittner
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Aktivity