IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

1. diel - Úvod do kolekcií a genericita vo Swift

Vitajte v online kurze zameranom na rôzne typy kolekcií programovacieho jazyka Swift.

Kolekcia

Pojem kolekcia označuje súbor dát, ktoré sú väčšinou rovnakého typu a slúžia na špecifický účel. Počas predchádzajúcich Swift kurzov sme sa už stretli s poľom (Array) ako základný kolekcií. Swift výber kolekcií veľmi zjednodušuje, pretože ponúka len hlavné tri. Základné pole už poznáme, neskôr si ukážeme pokročilejšie metódy a zoznámime sa so zvyšnými kolekciami Dictionary (slovník) a Set (množina).

Generické a všeobecné kolekcie

Keď sa zamyslíme nad tým, ako by sme si urobili vlastnú kolekciu, určite by sme po nejakej dobe dospeli k problému. Bol by ním dátový typ kolekcie. Chceli by sme si napr. Naprogramovať vlastný Array, vytvorili by sme triedu MojeArray.swift, do nej pridali príslušnej metódy a všetko potrebné. Pretože však chceme, aby bola naša kolekcia univerzálne a vedela teda ukladať napr. Ako Inty, tak užívateľov, bude problém s dátovým typom prvkov vnútri kolekcie. Existujú 2 varianty, ako tento problém vyriešiť, prakticky sa ale používa iba jedna. Tá lepšia samozrejme :-)

Všeobecné kolekcia

Vo Swiftu môžeme ľubovoľný dátový typ priradiť do typu Any. Ten by sme vo všeobecnej kolekcii mohli použiť a do kolekcie potom uložiť v podstate čokoľvek. Nevýhodou je, že sama kolekcia skutočný dátový typ prvkov nepozná a preto vie prvky navracať len ako všeobecné objekty. Po získaní prvku z kolekcie by sme museli riešiť pretypovanie.

Generické kolekcia

Generické kolekcia rieši problém s dátovým typom na úrovni jazyka Swift. Zavádza tzv. Genericitu. Zjednodušene povedané sa jedná o možnosť špecifikovať typ údajov až vo chvíli vytvorenie inštancie. V triede samotnej kolekcie sa potom pracuje s generickým typom, ktorý slúži ako zástupca pre budúce dátový typ. Môžeme si to predstaviť tak, že sa generický typ v triede zmení napr. Na String vo chvíli, keď vytvoríme jej inštanciu. Jedná sa teda o možnosť triedy nejakým spôsobom parametrizovať.

Generické Array už poznáme. Onen dátový typ (parameter) sa generickým triedam špecifikuje vo špicatých zátvorkách. Máme možnosť špecifikovať dátový typ iba raz, pri vytvorení kolekcie. Akékoľvek ďalšie pretypovania odpadá. Hoci sme používali na vytvorenie polí zjednodušenú syntax, bolo by ho možné vytvoriť aj takto:

var pole = Array<String>()
pole.append("položka")

let polozka = pole[0]

Zápis [String](), ktorý sme boli zvyknutí používať doteraz, by fungoval úplne rovnako.

Genericita

Genericita je samozrejme vlastnosť jazyka Swift a my ju máme možnosť vo svojich triedach používať.

Zatiaľ sa nebudeme zaťažovať tvorbou vlastnej kolekcie. Vytvorme si triedu, ktorá bude jednoducho spravovať jednu premennú. Premenná bude generická, teda ľubovoľného dátového typu. Založte si nový projekt, konzolovú aplikáciu s názvom Genericita. Pridajte si novú triedu, pomenujte ju teraz pre študijné účely iba Trida. V jej deklarácii pridáme generický parameter, ktorý pomenujeme T:

class Trida<T> {

}

Generických parametrov môžeme zadať vo špicatých zátvorkách viac, oddelíme ich čiarkou. Niekedy sa to môže hodiť, my sa s tým stretneme ďalej u generických slovníkov.

Presunieme sa do súboru main.swift, kde si vytvoríme inštanciu našej triedy:

let instance = Trida<Int>()

Nezabudneme na špicaté zátvorky ako u dátového typu, tak u konstruktoru. Teraz sme parametra T v tejto inštanciu triedy určili dátový typ Int. Rovnako tak si môžeme urobiť ďalší inštanciu tej istej triedy a parametra T dať úplne iný dátový typ, napr. String. Stačí nám teda 1 trieda pre viac dátových typov.

Pokračujme a vytvorme si v triede vlastnosť. T môžeme použiť ako bežný dátový typ:

private var promenna: T

Triede ešte dodáme konštruktor, ktorý premennú inicializuje.

init(promenna: T) {
    self.promenna = promenna
}

V main.swift aktualizujeme vytvorení inštancie:

let instance = Trida<Int>(promenna: 10)

Teraz inštancie obsahuje vlastnosť promenna, ktorá je typu Int a nadobúda hodnoty 10.

Môžeme dokonca pridať metódu, ktorá bude mať naviac ďalšie generický parameter (iný, než má trieda). Mohla by vyzerať napr. Nasledovne:

func porovnej<T2>(a: T2) -> Bool {
    return type(of: promenna) == type(of: a)
}

Metóda porovnáva dátový typ vlastnosti promenna s dátovým typom parametra. Mohla by s premennými ale samozrejme robiť čokoľvek iné. Skúsime si teda porovnať náš Int s nejakým iným typom:

instance.porovnej(a: "text")

Ďalšie konštrukcie

Pre úplnosť si ešte uveďme niekoľko konštrukcií.

Generický parameter triedy je možné bližšie špecifikovať, presnejšie obmedziť. Slúži na to dvojbodka priamo za generickým parametrom. Môžeme tak nastaviť, že udaný dátový typ musí napr. Obsahovať protokol Equatable (aby fungoval == operátor):

class Trida<T: Equatable> {
    // ...
}

Vďaka tomu môžeme na premenných typu T teraz vnútri triedy volať metódy z daného rozhrania. Samotné rozhranie môže opäť obsahovať generický parameter, aby sme generické typy mohli používať aj v hlavičkách jeho metód.

Môžeme tiež použiť zápis pomocou kľúčové slová where:

class Trida<T> where T:Equatable {
    // ...
}

Záleží, čo sa vám páči viac. Pre prehľadnosť by som odporučil where používať, keď máte viac špecifikácií.

Ak chceme špecifikovať viac protokolov, tak je v prvom variante zápise oddelíme pomocou &. Pri where stačí použiť čiarku a zopakovať pre aký parameter špecifikáciu uvádzame.

class Trida<T: Equatable & Comparable> {
    // ...
}
class Trida<T> where T: Equatable, T: Comparable {
    // ...
}

V budúcej lekcii, Filtrovanie a mapovanie polí vo Swift , sa znova pozrieme na pole a vysvetlíme si pokročilé metódy. Naučíte sa pole radiť a filtrovať podľa vlastných parametrov.


 

Všetky články v sekcii
Kolekcia vo Swift
Preskočiť článok
(neodporúčame)
Filtrovanie a mapovanie polí vo Swift
Článok pre vás napísal Filip Němeček
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje vývoji iOS aplikací (občas macOS)
Aktivity