Letní akce! Lákají tě IT školení C#, Javy a PHP v Brně? Přihlas se a napiš nám do zpráv kód "BRNO 500" pro slevu 500 Kč na libovolný brněnský kurz. Lze kombinovat se slevami uvedenými u školení i použít pro více kurzů. Akce končí 28.7.

Lekce 2 - Funkce a třídy v TypeScriptu

JavaScript TypeScript Funkce a třídy v TypeScriptu

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Úvod do TypeScriptu, jsme se podívali na úplné základy TypeScriptu a vysvětlili si, proč je dobré ho používat. Dnes se podíváme na funkce, které se od klasického JavaScriptu příliš neliší, a na třídy, které sice již implementuje ES6, ale ty v TypeScriptu mají jednu velkou výhodu. Ale o tom později.

Funkce (Functions)

Funkce v TypeScriptu se prakticky neliší od těch z JavaScriptu až na jednu věc, a to je typování. U funkce v TypeScriptu se typuje jak parametr funkce, tak její výstup. A to i v případě, že funkce žádný 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);

Výše je jednoduchá funkce pro vytváření seznamu, který je vložen přímo do DOM. Jak je vidět, přijímá parametr data, který je typu pole, a to obsahuje textové řetězce. Zároveň je zde ale něco nového, a to typ void. Ten nám říká, že funkce nic nevrací. Zároveň zde používáme for...of cyklus , který pravděpodobně znáte z JavaScriptu.

Většina věcí, která je obsažena v klasickém JavaScriptu, je použitelná i v TypeScriptu. To platí i pro cykly a podmínky. Vychází to z filozofie TypeScriptu, podle které nemá cenu implementovat věci, které standardní JavaScript obsahuje a fungují.

Přetížení funkce (Overloads)

Při psaní kódu se může stát, že jedna funkce bude velmi podobná druhé. Můžeme si ušetřit práci tím, že funkci přetížíme. To znamená, že bude mít několik hlaviček se stejným názvem, ale jinými parametry, které do ní vkládáme. Zde je například vidět, jak se funkce rozhoduje, kterou větu vypsat.

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.

Typování v této funkci se dá napsat i jinak, ale pro názornost jsem zvolil něco jednoduchého.

Třídy (Classes)

Nyní se podíváme na třídy tak, jak je implementuje TypeScript. Pokud třídy znáte, tato část pro vás bude pravděpodobně jen opakování. Pokud je neznáte, doporučil bych vám minimálně článek o OOP v JavaScriptu První objektová aplikace v JS, ve kterém se dozvíte, co OOP je a k čemu jsou třídy.

Na začátku článku jsem zmínil, že třídy v TypeScriptu mají oproti implementaci z ES6 výhodu. Třídy v JavaScriptu totiž nefungují ve starších prohlížečích, v IE dokonce vůbec. Naštěstí TypeScript nám je přeloží a fungovat budou. Nyní si rychle prolétneme základní pojmy a uvedeme si několik příkladů. Budu používat souběžně anglické názvy, aby nás to nemátlo a abychom se něco naučili.

Konstruktor (Constructor)

Konstruktor je metoda, která se volá při vytvoření instance třídy. Slouží k nastavení vnitřního stavu objektu a k provedení případné inicializace.

This

Klíčové slovo this obsahuje referenci na instanci objektu, ve kterém se zrovna nacházíme. Používáme jej, když chceme přistoupit ke členům dané instance. Jako členy nazýváme atributy nebo metody.

Modifikátory přístupu (Access modifiers)

Další důležitou součástí OOP v TypeScriptu jsou modifikátory přístupu. Ty určují, odkud a jakým způsobem je atribut nebo metoda třídy dostupná. TypeScript používá ve třídách 3 základní modifikátory:

public (výchozí)

Modifikátor public je na rozdíl např. od jazyka C# výchozí. Pokud tedy nespecifikujeme jinak, všechny členy třídy budou plně přístupné zvenku. Udělejme si malou ukázku:

class Zvire {

        public jmeno: string;

        public constructor(jmenujeSe: string) {
                this.jmeno = jmenujeSe;
        }

        public utikej(jakDaleko: number) {
                console.log(`${this.jmeno} utíkal ${jakDaleko}m.`);
        }
}

Konstruktor při inicializaci nastaví atribut jmeno. Toho dosáhneme použitím slovíčka this. Atribut jmeno je použitý v metodě utikej(). Tato metoda vytváří větu, která nám řekne, jak naše zvíře utíkalo daleko.

Vytvoření instance a vypsání jména zvířete by vypadalo takto:

let gazela = new Zvire('Gonzales');
console.log(gazela.jmeno);

private

Pokud je člen označen jako private, není možné k němu přistoupit jinak než přímo zevnitř třídy. Upravme jméno našeho zvířete tak, aby bylo jen soukromé:

class Zvire {

        private jmeno: string;

        public constructor(jmenujeSe: string) {
                this.jmeno = jmenujeSe;
        }

        public utikej(jakDaleko: number) {
                console.log(`${this.jmeno} utíkal ${jakDaleko}m.`);
        }
}

Níže je vidět, že pokud se nyní pokusíme jméno zvířete vypsat mimo třídu Zvire, dostaneme chybu:

let gazela = new Zvire('Gonzales');
console.log(gazela.jmeno); // Tento řádek nyní způsobí chybu

V příkazovém řádku se objeví 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čováním co největšího množství členů jako private se výrazně zminimalizuje možnost rozbít objekt zvenčí tím, že jej použijeme jinak, než zamýšlel jeho autor. I když mnohem větší význam má skrývat nějaké pomocné atributy tříd, např. logger, i jméno si nyní nemůžeme např. omylem vymazat:

gazela.jmeno = ""; // Tento řádek opět vyvolá chybu, jelikož jmeno je private

Na změnu jména bychom např. vystavili speciální metodu zmenJmeno(), kterou by bylo nutné explicitně zavolat.

protected

Modifikátor protected se podobá private. Na rozdíl od něj však umožňuje i přístup k členům ze tříd, které z dané třídy dědí, tedy z potomků. Dědičnost si ještě popíšeme o kousek dále.

readonly

Atributy, které mají modifikátor readonly, je možné nastavit pouze při deklaraci nebo v konstruktoru. V ostatních případech jsou, jak název napovídá, pouze pro čtení. Jedná se opět o mechanismus, který nám pomáhá předejít nechtěným změnám, způsobenými např. chybami v kódu.

Dědičnost (Inheritance)

Stejně jako ve většině objektově orientovaných jazyků i v TypeScriptu ze sebe mohou třídy dědit. Dědění umožňuje rozšířit základní třídu o nové atributy nebo metody a provádí se klíčovým slovem extends. Třída Opice níže rozšiřuje naše zvíře a tím obsahuje všechny jeho atributy a metody. Navíc přináší svoji novou metodu, která je výhradně opičí, a to je houpejSe(). Protože chceme vědět, kolik mají opice běžně ocasů, zavedli jsme atribut pocetOcasu. Ten je pouze pro čtení, protože nechceme, aby náš opičák o ocas přišel.

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šimněte si, že modifikátor přístupu k atributu jmeno ve třídě Zvire jsme nastavili na protected. To proto, abychom k němu mohli přistupovat v potomkovi Opice, v metodě houpejSe().

Snad se vám všem podařilo pochopit, jak třídy fungují. V přiloženém archivu najdete kód z tohoto článku. Kompilaci ze souboru .ts nechám na vás :-) Příště se v lekci Interface (rozhraní) v TypeScriptu podíváme na rozhraní (interface).


 

Stáhnout

Staženo 7x (1.31 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

 

Článek pro vás napsal Jiří Kvapil
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje profesionálně front-endu a jezdí na všem co má kola.
Miniatura
Předchozí článek
Úvod do TypeScriptu
Miniatura
Všechny články v sekci
TypeScript
Miniatura
Následující článek
Interface (rozhraní) v TypeScriptu
Aktivity (4)

 

 

Komentáře

Avatar
Michal Žůrek - misaz:29. června 12:50

Připomínky:

Klíčové slovo this obsahuje referenci na instanci objektu, ve kterém se zrovna nacházíme.

Nemusí být pravda. Následujíc ukázka bude volat v pravidelném intervalu metodu pozdrav a this v metodě pozdrav nebude obsahovat, to co by si tam čekal. Pokud kód poběží ve webovém prohlížeči, tak tam bude obsahovat objekt Window.

class Zdravic {

    private jmeno: string;

    constructor(jm: string) {
        this.jmeno = jm;
    }

    pozdrav() {
        console.log("Zdravím " + this.jmeno);
    }
}

var zdravic = new Zdravic("Frantu");
setInterval(zdravic.pozdrav, 1000);

Níže je vidět, že pokud se nyní pokusíme jméno zvířete vypsat mimo třídu Zvire, dostaneme chybu:

to ale dostaneme při kompilaci, za běhu by kód normálně proběhl protože TypeScript všechny členy z výkonových důvodů exportuje jako public. Hacknout si to s TypeScriptu lze docela snadno.

console.log((gazela as any).jmeno);

což se v exportovaném JS projeví jako

console.log(gazela.jmeno);

ale toto normálně nemá smyls dělat, rozbíjí to kód a porušujé dobré zvyky a zásady.

Jinak je článek dobrý.

Odpovědět 29. června 12:50
Nesnáším {}, proto se jim vyhýbám.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 1 zpráv z 1.