2. diel - Funkcie a triedy v TypeScriptu
V minulej lekcii, Funkcie v TypeScriptu , sme sa pozreli na tvorbu funkcií a ich vlastnosti.
V minulej lekcii, Funkcie v TypeScriptu , sme sa pozreli na úplné základy TypeScriptu a vysvetlili si, prečo je dobré ho používať. Dnes sa pozrieme na funkcie, ktoré sa od klasického JavaScriptu príliš nelíši, a na triedy, ktoré síce už implementuje ES6, ale tie v TypeScriptu majú jednu veľkú výhodu. Ale o tom neskôr.
Funkcia (Functions)
Funkcie v TypeScriptu sa prakticky nelíši od tých z JavaScriptu až na jednu vec, a to je typovanie. U funkcie v TypeScriptu sa typu Jak parameter funkcie, tak jej výstup. A to aj v prípade, že funkcia žiadny výstup nemá.
function vytvorSeznam(data: string[]): void { const element = document.getElementById('seznam'); for (const polozka of data) { const li = document.createElement('li'); const textNodePolozka = document.createTextNode(polozka); li.appendChild(textNodePolozka); element.appendChild(li); } } const polozky: string[] = ['kartáček', 'pasta', 'ponožky'] vytvorSeznam(polozky);
Vyššie je jednoduchá funkcia pre vytváranie zoznamu, ktorý je vložený
priamo do DOM. Ako je vidieť, prijíma parameter data
, ktorý je
typu pole, a to obsahuje textové reťazce. Zároveň je tu ale niečo nové, a
to typ void
. Ten nám hovorí, že funkcia nič nevracia. Zároveň
tu používame for...of
cyklus, ktorý pravdepodobne poznáte z
JavaScriptu.
Väčšina vecí, ktorá je obsiahnutá v klasickom JavaScriptu, je použiteľná aj v TypeScriptu. To platí aj pre cykly a podmienky. Vychádza to z filozofie TypeScriptu, podľa ktorej nemá cenu implementovať veci, ktoré štandardné JavaScript obsahuje a fungujú.
Preťaženia funkcie (Overloads)
Pri písaní kódu sa môže stať, že jedna funkcia bude veľmi podobná druhej. Môžeme si ušetriť prácu tým, že funkciu preťažíme. To znamená, že bude mať niekoľko hlaviček s rovnakým názvom, ale inými parametrami, ktoré do nej vkladáme. Tu je napríklad vidieť, ako sa funkcia rozhoduje, ktorú vetu vypísať.
function hledej(ulice: number, mesto: string): void; function hledej(ulice: string, mesto: string): void; function hledej(ulice, mesto): void { if (typeof ulice !== 'number') { console.log(`Adresa je ${ulice}, ${mesto}.`); } else if (typeof ulice !== 'string') { console.log(`${mesto} nemá ulice, ale číslo domu je ${ulice}.`); } } hledej('Lázeňská', 'Mariánské Lázně'); // Adresa je Lázeňská, Mariánské Lázně. hledej(122, 'Králíčkov'); // Králíčkov nemá ulice, ale číslo domu je 122.
Typovanie v tejto funkcii sa dá napísať aj inak, ale pre názornosť som zvolil niečo jednoduché.
Triedy (Classes)
Teraz sa pozrieme na triedy tak, ako ich implementuje TypeScript. Ak triedy poznáte, táto časť pre vás bude pravdepodobne len opakovanie. Ak ich nepoznáte, odporučil by som vám minimálne článok o OOP v JavaScripte Prvé objektová aplikácie v JS, v ktorom sa dozviete, čo OOP je a na čo sú triedy.
Na začiatku článku som spomenul, že triedy v TypeScriptu majú oproti implementáciu z ES6 výhodu. Triedy v JavaScriptu totiž nefungujú v starších prehliadačoch, v IE dokonca vôbec. Našťastie TypeScript nám ich preloží a fungovať budú. Teraz si rýchlo preletíme základné pojmy a uvedieme si niekoľko príkladov. Budem používať súbežne anglické názvy, aby nás to neklame a aby sme sa niečo naučili.
Konštruktor (Constructor)
Konštruktor je metóda, ktorá sa volá pri vytvorení inštancie triedy. Slúži na nastavenie vnútorného stavu objektu a na vykonanie prípadnej inicializácia.
This
Kľúčové slovo this
obsahuje referenciu na inštanciu
objektu, v ktorom sa práve nachádzame. Používame ho, keď chceme pristúpiť
k členom danej inštancie. Ako členmi nazývame atribúty alebo metódy.
Modifikátory prístupu (Access modifiers)
Ďalšou dôležitou súčasťou OOP v TypeScriptu sú modifikátory prístupu. Tie určujú, odkiaľ a akým spôsobom je atribút alebo metóda triedy dostupná. TypeScript používa v triedach 3 základné modifikátory:
Public (predvolené)
Modifikátor public
je na rozdiel napr. Od jazyka C # predvolené. Ak teda nešpecifikuje inak, všetky členmi
triedy budú plne prístupné zvonku. Urobme si malú ukážku:
class Zvire { public jmeno: string; public constructor(jmenujeSe: string) { this.jmeno = jmenujeSe; } public utikej(jakDaleko: number) { console.log(`${this.jmeno} utíkal ${jakDaleko}m.`); } }
Konštruktor pri inicializácii nastaví atribút jmeno
. To
dosiahneme použitím slovíčka this
. Atribút jmeno
je použitý v metóde utikej()
. Táto metóda vytvára vetu,
ktorá nám povie, ako naše zviera utekalo ďaleko.
Vytvorenie inštancie a vypísanie mena zvieraťa by vyzeralo takto:
let gazela = new Zvire('Gonzales'); console.log(gazela.jmeno);
Private
Ak je člen označený ako private
, nie je možné k nemu
pristúpiť inak než priamo zvnútra triedy. Upravme meno nášho zvieraťa
tak, aby bolo len súkromné:
class Zvire { private jmeno: string; public constructor(jmenujeSe: string) { this.jmeno = jmenujeSe; } public utikej(jakDaleko: number) { console.log(`${this.jmeno} utíkal ${jakDaleko}m.`); } }
Nižšie je vidieť, že ak sa teraz pokúsime meno zvieraťa vypísať mimo
triedu Zvire
, dostaneme chybu:
let gazela = new Zvire('Gonzales'); console.log(gazela.jmeno); // Tento řádek nyní způsobí chybu
V príkazovom riadku sa objaví chybový text:
C:\Users\David\Desktop>tsc skript.ts skript.ts:14:20 - error TS2341: Property 'jmeno' is private and only accessible with in class 'Zvire'. 14 console.log(gazela.jmeno);
Označovaním čo najväčšieho množstva členov ako private sa výrazne zminimalizuje možnosť rozbiť objekt zvonku tým, že ho použijeme inak, než zamýšľal jeho autor. Aj keď oveľa väčší význam má skrývať nejaké pomocné atribúty tried, napr. Logger, aj meno si teraz nemôžeme napr. Omylom vymazať:
gazela.jmeno = ""; // Tento řádek opět vyvolá chybu, jelikož jmeno je private
Na zmenu mena by sme napr. Vystavili špeciálnu metódu
zmenJmeno()
, ktorú by bolo nutné explicitne zavolať.
Protected
Modifikátor protected
sa podobá private
. Na
rozdiel od neho však umožňuje aj prístup k členom z tried, ktoré z danej
triedy dedia, teda z potomkov. Dedičnosť si ešte popíšeme o kúsok
ďalej.
Readonly
Atribúty, ktoré majú modifikátor readonly, je možné nastaviť len pri deklarácii alebo v konštruktory. V ostatných prípadoch sú, ako názov napovedá, len na čítanie. Ide opäť o mechanizmus, ktorý nám pomáha predísť nechceným zmenám, spôsobenými napr. Chybami v kóde.
Dedičnosť (Inheritance)
Rovnako ako vo väčšine objektovo orientovaných jazykov aj v TypeScriptu
zo seba môžu triedy dediť. Dedenie umožňuje rozšíriť základnú triedu o
novej atribúty alebo metódy a vykonáva sa kľúčovým slovom
extends
. Trieda Opice
nižšie rozširuje naše zviera
a tým obsahuje všetky jeho atribúty a metódy. Navyše prináša svoju novú
metódu, ktorá je výhradne opičie, a to je houpejSe()
. Pretože
chceme vedieť, koľko majú opice bežne chvostov, zaviedli sme atribút
pocetOcasu
. Ten je len na čítanie, pretože nechceme, aby náš
opičiak o chvost prišiel.
class Zvire { protected jmeno: string; public constructor(jmenujeSe: string) { this.jmeno = jmenujeSe; } public utikej(jakDaleko: number) { console.log(`${this.jmeno} utíkal ${jakDaleko}m.`); } } class Opice extends Zvire { readonly pocetOcasu = 1; houpejSe() { console.log(`Opicak ${this.jmeno} se houpe.`); } } let pepa = new Opice('Pepa'); pepa.utikej(150); // Pepa utíkal 150m. pepa.houpejSe(); // Opicak pepa se houpe.
Všimnite si, že modifikátor prístupu k atribútu jmeno
v
triede Zvire
sme nastavili na protected
. To preto, aby
sme k nemu mohli pristupovať v potomkovi Opice
, v metóde
houpejSe()
.
Snáď sa vám všetkým podarilo pochopiť, ako triedy fungujú. V priloženom archíve nájdete kód z tohto článku. Kompiláciu zo súboru .ts nechám na vás Nabudúce sa v lekcii Interface (rozhranie) v TypeScriptu pozrieme na rozhraní (interface).
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 107x (1.31 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript