4. díl - Swift - Typový systém a chyby

Ostatní jazyky Swift Swift - Typový systém a chyby

Typový systém

Typový systém je důležitou součástí každého jazyka. Jedná se o program, který kontroluje, zda neděláme nepovolené operace s typy. Například, jestli se nepokoušíme přiřadit číslo k řetězci, neboli zda se nesnažíme do proměnné typu String přiřadit [Int].

Typový systém se dělí na dvě části: Typování proměnných a Typová kontrola.

Typování proměnných

Typování proměnných je základem každého jazyka. Dělí se na tři (nejvýznamnější) části.

Statické typování

Statické typování je přístup, u kterého je v okamžiku deklarace proměnné uložen také její typ. Poté už do ní musíme ukládat pouze tento typ.

Výhody: lepší kontrola nad kódem, rychlejší hledání chyb, většinu kontroly ohledně typových operací (např. aritmetika) provede již kompilátor. Nevýhody: aplikace je mnohem méně "pružná", funkce jsou velice omezeny (musíme třikrát deklarovat funkci 'f', která provádí operace nad typy 'Int', 'Float', 'Double'), delší kód.

Dynamické typování

Dynamicky typované jazyky ukládají pouze jméno proměnné a její hodnotu. Kdykoli do ní něco ukládáme, je její předchozí hodnota zapomenuta a s ní i její typ.

Výhody: rychlejší vývoj, "pružnost" funkcí, (mnohdy) kratší kód. Nevýhody: těžší debugging, o chybě se dozvíte až za běhu.

Tyto dva přístupy jsou trefně přirovnávány: Statické typování je jako jet v tanku - bezpečné a pomalé. Dynamické je jako překračovat rychlost na dálnici motorkou - vzrušující a nebezpečné.

"Kachní" typování

Duck typing je speciální přístup k typům proměnných. Její typ je odvozen z rozhraní její hodnoty. Její myšlenku lze vyjádřit takto: Pokud vidím ptáka, který chodí jako kachna, plave jako kachna a kváká jako kachna, tak o tomto ptáku tvrdím, že je to kachna. - Duck Typing. Wikipedia: the free encyclopedia [online]. San Francisco (CA): Wikimedia Foundation, 2001- [cit. 2015-08-13]. Dostupné z: https://cs.wikipedia.org/…/Duck-typing.

Swift je typován staticky, zejména jeho charakteristikou je "bezpečný jazyk".

Typová kontrola

Typová kontrola je kontrolování zejména typů užitých v operacích (aritmetika). Dělí se na dva typy.

Silná typová kontrola

Silná kontrola striktně kontroluje každičký typ v operaci. Jakmile objeví neplatný typ, vyhodí chybu. Používá se zejména u statických jazyků (díky předem známým typům proměnných).

Slabá typová kontrola

Naproti tomu slabou kontrolou vám projde i odečítání čísla od řetězce. Chybu dostanete až ze běhu, či (čehož je schopen JavaScript) chybu nedostanete vůbec. U této kontroly jsou výsledky těchto operací zajímavé. (Např. 32 + "Hello" = NaN ale "Hello" + 32 = "Hello32")

Swift je jazyk se silnou typovou kontrolou => je považován za typově bezpečný.

To byla malá vsuvka ohledně typů a teď začneme se zajímavou částí jazyka...

Chyby

Chyba už na vás (i ve Swiftu předpokládám) někdy "vybafla". Bohužel se jim ale prakticky nedá vyhnout. Naštěstí nám o nich často překladač řekne. :)

Napišme si jednoduchou funkci:

func f(a: Int) -> Int {
    if a < 0 {
        print("Napište prosím číslo větší než 0!")
        return -1
    }

    return a + 1
}

var a = f(-12)

Co nám vrátí funkce? -1 a vypíše chybovou hlášku. Jenomže to může mít vedlejší efekt a zejména u větší aplikace to je problém. Hodila by se nám "opravdová" chyba.

Ta se vytvoří pomocí enumu, který dědí z ErrorType:

enum Chyby: ErrorType {
    case Chyba(hláška: String), ČísloJeMenšíNežNula
}

Chyby tedy mohou mít argumenty, ale nemusí.

A nyní naší chybu vyvoláme, což uděláme pomocí slova throw. Zároveň ale musíme funkci označit, že může vyvolat chybu:

func f(a: Int) throws -> Int {
    if a < 0 {
        throw Chyby.Chyba(hláška: "Zadejte prosím číslo větší než 0!")
    }

    return a + 1
}

A nyní zpět k našemu přiřazení, musíme ho upravit, protože už kompilátor vidí, že naše funkce něco může vyhodit a nelíbí se mu to.

Nebezpečný kód píšeme sem:

do {
    // Nebezpečný kód
} catch ... {   // Zde může být upřesněna chyba, ale nemusí, počet catch je neomezený ("univerzální" chybově neupřesněný catch musí být poslední (nechápejte jako že je vyžadován)).
    // Co se má dít při selhání
}

Plus při přiřazování musíme použít slovo try:

var a = try f(-12) // Slovo píšeme vždy jednou na začátku výrazu.

Náš výsledný kód tedy vypadá takto:

enum Chyby: ErrorType {
    case Chyba(hláška: String), ČísloJeMenšíNežNula
}

func f(a: Int) throws -> Int {
    if a < 0 {
        throw Chyby.Chyba(hláška: "Zadejte prosím číslo větší než 0!")
    }

    return a + 1
}

do {
    let a = try f(-12)
} catch Chyby.Chyba(hláška: "Zadejte prosím číslo větší než 0!") {
    print("Zadali jste číslo menší než 0!")
}

Pokud nechceme chybu odchytit, nemusíme nebezpečný kód "obalit" do ... catch, musíme však každou nebezpečnou část kódu označit slovem try a naše aplikace na místě chyby skončí.

Vstup od uživatele aneb Začíná peklo

Swift je velice jednoduchý a bezpečný programovací jazyk, ale má pár nedostatků. Mezi ty patří například vstup od uživatele do příkazové řádky. Není to ještě tak složité, ale stejně to není elegantní - Swift byl také vytvořen primárně pro aplikace s grafickým rozhraním.

Ale pojďme rovnou k věci: Vstup odněkud přichází. To někde je standardní vstup, o nějž se stará třída NSFileHandle a z ní můžeme číst data, které pak převedeme na text a to je náš vstup.

Abychom nemuseli tento kód psát stále dokola, napíšeme si pro to funkci:

func vstup(zpráva: String) -> String {
    print(zpráva, appendNewline: false) // Vypíše text bez nevého řádku.

    // Vytvoří prostředníka mezi námi a standardním vstupem.
    let keyboard = NSFileHandle.fileHandleWithStandardInput()
    let inputData = keyboard.availableData // Přečte vstupní data.

    // Převede vstupní data na text kódovaný jako UTF-8 a změní ho na String.
    return NSString(data: inputData, encoding:NSUTF8StringEncoding) as! String
}

Na posledním řádku si všimněte konverze s vynuceným rozbalením as! (možno také napsat as? pro nenucené rozbalení). Nejdříve se hodnota rozbalí, jak jsme si minule vysvětlili, a pak se převede na jiný typ.

Když potom náš kód spustíme:

let jméno = vstup("Napiš své jméno: ")

Kód vypíše zprávu a počká do stisknutí klávesy Enter.

Příště si vysvětlíme konverzi typů a s nimi spojenou dědičnost.


 

  Aktivity (3)

Článek pro vás napsal jan.ruzicka01
Avatar
Autor se věnuje programovaní v Pythonu, Ruby, Javě a trochu C#. Dříve tvořil aplikace v C/C++. Nyní se zajímá o webové technologie a tvorbu virtuálních strojů (/programovacího jazyka).

Jak se ti líbí článek?
Celkem (1 hlasů) :
55555


 


Miniatura
Všechny články v sekci
Swift

 

 

Komentáře

Avatar
Polymath
Člen
Avatar
Polymath:

Bude nějaké pokračování?

 
Odpovědět 8.12.2015 16:53
Avatar
Ondřej Měchura:

taky bych nějáké ocenil

 
Odpovědět 8.12.2015 17:04
Avatar
jan.ruzicka01
Redaktor
Avatar
Odpovídá na Ondřej Měchura
jan.ruzicka01:

Pokračování určitě bude, jenom ne hned, teď máme období testů, takže se tomu budu věnovat až kolem vánoc.

Odpovědět 8.12.2015 21:24
';' je má jediná noční můra...
Avatar
Zdeněk Bečka:

Také se připojuji s prosbou o pokračování. Děkuji, pěkná práce.

 
Odpovědět 28. ledna 21:49
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 4 zpráv z 4.