8. diel - Aréna s mágom (dedičnosť a polymorfizmus) vo Swift
V minulej lekcii, Dedičnosť a polymorfizmus vo Swift , sme si vysvetlili dedičnosť a polymorfizmus.
Dnes máme sľúbené, že si ich vyskúšame v praxi. Bude to opäť na našej
aréne, kde z bojovníka oddědíme mága. Tento Swift tutoriál už patrí k
tým náročnejším a bude tomu tak aj u ďalších. Preto si priebežne
precvičujte prácu s objektmi a tiež vymýšľajte nejaké svoje aplikácie,
aby ste si zažili základné veci. To, že je tu prítomný celý online kurz
neznamená, že ho celý naraz prečítate a pochopíte Snažte sa programovať
priebežne.

0
. Každé kolo sa bude
mana zvyšovať o 10 a mág bude podnikať len bežný útok. Akonáhle sa mana
úplne doplní, opäť bude môcť magický útok použiť. Mana bude zobrazená
grafickým ukazovateľom, rovnako ako život.
Vytvoríme teda triedu Mag
v súbore
Bojovnik.swift
, zdedíme ju z Bojovnik
a dodáme ju
vlastnosti, ktoré chceme oproti bojovníkovi navyše. Bude teda vyzerať
takto:
class Mag: Bojovnik { private var mana : Double private var maxMana : Double private var magickyUtok : Int }
V mágovi nemáme zatiaľ prístup ku všetkým premenným, pretože sú v
bojovníkovi nastavené ako privátne. Musíme triedu Bojovnik
ľahko upraviť. Zmeníme modifikátory private
u vlastností na
fileprivate
. Budeme potrebovať len
kostka
a jmeno
, ale pokojne nastavíme ako
fileprivate
všetky vlastnosti charakteru, pretože sa v
budúcnosti môžu hodiť, keby sme sa rozhodli oddědit ďalšie typy
bojovníkov. Naopak vlastnosť zprava
nie je vhodné nastavovať
ako fileprivate
, pretože nesúvisí s bojovníkom, ale s nejakou
vnútornou logikou triedy. Trieda teda bude vyzerať nejako takto:
class Bojovnik { fileprivate var jmeno : String fileprivate var zivot : Double fileprivate var maxZivot : Double fileprivate var utok : Int fileprivate var obrana : Int fileprivate var kostka : Kostka private var zprava : String = "" // ...
Prejdime ku konstruktoru.
Viac konštruktor vo Swift
Nastala ideálnu príležitosť vysvetliť si, ako vo Swiftu funguje viac
konstruktoru, respektíve metód init()
. Swift rozlišuje tzv.
Designated a convenience konštruktory. Designated by sa dalo najlepšie
preložiť ako "označený" a je to vlastne primárnou / predvolený
konštruktor. Ak máme iba jeden init()
, tak je automaticky
designated.
Ak chceme mať v triede viac konstruktoru, aby sa dala jej inštancie
vytvoriť na základe rôznych parametrov, tak musíme mať tie ďalšie
označené slovíčkom convenience
, čo by sa dalo označiť ako
pohodlný. A tieto konštruktory musia cez self
volať designated
konštruktor. Nie je to nič zložité a môžeme si ukázať jednoduchý
prípad, ak by sme chceli nášho bojovníka vytvoriť bez parametrov. Vyzeralo
by to asi takto:
init(jmeno: String, zivot: Int, utok: Int, obrana: Int, kostka: Kostka) { self.jmeno = jmeno self.zivot = Double(zivot) self.maxZivot = self.zivot self.utok = utok self.obrana = obrana self.kostka = kostka } convenience init() { self.init(jmeno: "Standardní válečník", zivot: 100, utok: 20, obrana: 10, kostka: Kostka()) }
Teraz môžeme zadať parametre bojovníka, použiť prvý konštruktor, ale
aj napísať iba new Bojovnik()
, čím sa použije konštruktor
druhý. Ten pomocou volania designated konstruktoru nastaví predvolené
hodnoty.
Konštruktor potomka
Swift dedí konstruktory iba v špecifických prípadoch. Konštruktor bude
zdedený, ak novým vlastnostiam potomka nastavíme predvolené hodnoty (alebo
budú Optional
) a tým pádom nie je vyžadovaný konštruktor.
Rovnako tak nesmieme vytvoriť designated init()
metódu, aby sme
neprišli o zdedený konštruktor. Convenience konštruktory je možné
pridať.
V našom prípade mága bude lepšie vytvoriť vlastný konštruktor, pretože máme vlastnosti navyše, ktoré v ňom chceme nastavovať.
Definujeme si teda konštruktor v potomkovi, ktorý berie parametre potrebné pre vytvorenie bojovníka a niekoľko parametrov navyše pre mága.
V konštruktor potomkov je nutné vždy volať konštruktor predka. Je to z toho dôvodu, že bez volania konstruktoru nemusí byť inštancie správne inicializovaná. Konštruktor predka nevoláme iba v prípade, že žiadny nemá. Náš konštruktor musia mať samozrejme všetky parametre potrebné pre predka plus tie nové, čo má navyše potomok. Niektoré potom odovzdáme predkovi a niektoré si spracujeme sami. Konštruktor predka je nutné zavolať až nakoniec, inak Swift zobrazí chybu.
Vo Swift existuje kľúčové slovo super
,
ktoré je podobné nami už známemu self
. Na rozdiel od
self
, ktoré odkazuje na konkrétnu inštanciu triedy,
super
odkazuje na predka. My teda môžeme
zavolať konštruktor predka s danými parametrami a potom vykonať navyše
inicializáciu pre mága.
Konštruktor mága bude teda vyzerať takto:
init(jmeno: String, zivot: Int, utok: Int, obrana: Int, kostka: Kostka, mana: Int, magickyUtok: Int) { self.mana = Double(mana) self.maxMana = self.mana self.magickyUtok = magickyUtok super.init(jmeno: jmeno, zivot: zivot, utok: utok, obrana: obrana, kostka: kostka) }
Rovnako môžeme volať aj iný konštruktor v tej istej triede
(nie predka), len miesto super
použijeme self
.
Opäť sme si previedli manu interne na Double
, čoskoro
uvidíte prečo.
Presuňme sa teraz do main.swift
a druhého bojovníka (Shadow)
zmeňme na mága, napr. Takto:
let gandalf : Bojovnik = Mag(jmeno: "Gandalf", zivot: 60, utok: 15, obrana: 12, kostka: kostka, mana: 30, magickyUtok: 45)
Zmenu samozrejme musíme urobiť aj v riadku, kde bojovníka do arény
vkladáme. Všimnite si, že mága ukladáme do premennej typu
Bojovnik
. Nič nám v tom nebráni, pretože bojovník je jeho
predok. Rovnako tak si môžeme typ premennej zmeniť na Mag
. Keď
aplikáciu teraz spustíme, bude fungovať úplne rovnako, ako predtým. Mág
všetko dedí z bojovníka a zatiaľ teda funguje ako bojovník.
Polymorfizmus a prepisovanie metód
Bolo by výhodné, keby objekt Arena
mohol s mágom pracovať
rovnako ako s bojovníkom. My už vieme, že takémuto mechanizmu hovoríme
polymorfizmus. Aréna zavolá na objekte metódu
utoc()
so súperom v parametri. Nestará sa o to, či bude útok
vykonávať bojovník alebo mág, bude s nimi pracovať rovnako. U mága si teda
prepíšeme metódu utoc()
z predka. Prepíšeme
zdedenú metódu tak, aby útok pracoval s mannou, hlavička metódy však
zostane rovnaká.
Prepísanie metódy z predka vykonáme v potomkovi pomocou slovíčka
override
, ako si ukážeme nižšie.
Keď sme pri metódach, budeme ešte určite používať metódu
nastavZpravu()
, tá je však privátne. Označme ju ako
fileprivate
:
fileprivate func nastavZpravu(_ zprava: String)
Pri návrhu bojovníka sme samozrejme mali myslieť na to, že sa z neho bude
dediť a už označiť vhodné vlastnosti a metódy ako
fileprivate
.
Teraz sa vráťme do potomka a poďme prepísať metódu utoc()
.
Metódu normálne definujeme v Mag.swift
tak, ako sme zvyknutí.
Jej definíciu ale začneme slovom override
,
ktoré značí, že si sme vedomí toho, že sa metóda zdedila, ale prajeme si
zmeniť jej správanie.
override func utoc(souper: Bojovnik)
Správanie metódy utoc()
nebude nijako zložité. Podľa
hodnoty many buď vykonáme bežný útok alebo útok magický. Hodnotu many
potom buď zvýšime o 10 alebo naopak znížime na 0
v prípade
magického útoku.
override func utoc(souper: Bojovnik) { var uder = 0 // Mana není naplněna if mana < maxMana { mana += 10; if (mana > maxMana) { mana = maxMana } uder = utok + kostka.hod(); nastavZpravu("\(jmeno) útočí s úderem za \(uder) hp") } else { // Magický útok uder = magickyUtok + kostka.hod() nastavZpravu("\(jmeno) použil magii za \(uder) hp") mana = 0 } souper.branSe(uder: uder) }
Kód je asi zrozumiteľný. Všimnite si obmedzenia many na
maxMana
, môže sa nám totiž stať, že túto hodnotu presiahne,
keď ju zvyšujeme o 10. Keď sa nad kódom zamyslíme, tak útok vyššie v
podstate vykonáva pôvodnej metóda utoc()
. Iste by bolo
prínosné zavolať podobu metódy na predkovi namiesto toho, aby sme správanie
odpisovali. K tomu opäť použijeme super
:
- App
- Bojovnik.swift
- Arena.swift
- main.swift
- Kostka.swift
{SWIFT} class Bojovnik: CustomStringConvertible { fileprivate var jmeno : String fileprivate var zivot : Double fileprivate var maxZivot : Double fileprivate var utok : Int fileprivate var obrana : Int fileprivate var kostka : Kostka private var zprava : String = "" init(jmeno: String, zivot: Int, utok: Int, obrana: Int, kostka: Kostka) { self.jmeno = jmeno self.zivot = Double(zivot) self.maxZivot = self.zivot self.utok = utok self.obrana = obrana self.kostka = kostka } convenience init() { self.init(jmeno: "Standardní válečník", zivot: 100, utok: 20, obrana: 10, kostka: Kostka()) } var description: String { return jmeno } func nazivu() -> Bool { return zivot > 0 } func grafickyZivot() -> String { var s = "[" let celkem : Double = 20 var pocet : Double = round((zivot / maxZivot) * celkem) if (pocet == 0) && (nazivu()) { pocet = 1 } for _ in 0..<Int(pocet) { s += "#" } s = s.padding(toLength: Int(celkem) + 1, withPad: " ", startingAt: 0) s += "]" return s } func utoc(souper: Bojovnik) { let uder = utok + kostka.hod() nastavZpravu("\(jmeno) útočí s úderem za \(uder) hp") souper.branSe(uder: uder) } func branSe(uder: Int) { let zraneni = Double(uder - (obrana + kostka.hod())) var zprava = "" if (zraneni > 0) { zivot -= zraneni zprava = "\(jmeno) utrpěl poškození \(Int(zraneni)) hp" if (zivot <= 0) { zivot = 0 } } else { zprava = "\(jmeno) odrazil útok" } nastavZpravu(zprava) } fileprivate func nastavZpravu(_ zprava: String) { self.zprava = zprava } func vratPosledniZpravu() -> String { return zprava } } class Mag: Bojovnik { private var mana : Double private var maxMana : Double private var magickyUtok : Int init(jmeno: String, zivot: Int, utok: Int, obrana: Int, kostka: Kostka, mana: Int, magickyUtok: Int) { self.mana = Double(mana) self.maxMana = self.mana self.magickyUtok = magickyUtok super.init(jmeno: jmeno, zivot: zivot, utok: utok, obrana: obrana, kostka: kostka) } override func utoc(souper: Bojovnik) { var uder = 0 // Mana není naplněna if mana < maxMana { mana += 10; if (mana > maxMana) { mana = maxMana } super.utoc(souper: souper) nastavZpravu("\(jmeno) útočí s úderem za \(uder) hp") } else { // Magický útok uder = magickyUtok + kostka.hod() nastavZpravu("\(jmeno) použil magii za \(uder) hp") mana = 0 } souper.branSe(uder: uder) } } {/SWIFT}
{SWIFT} class Arena { private var bojovnik1 : Bojovnik private var bojovnik2 : Bojovnik private var kostka : Kostka init(bojovnik1: Bojovnik, bojovnik2: Bojovnik, kostka: Kostka) { self.bojovnik1 = bojovnik1 self.bojovnik2 = bojovnik2 self.kostka = kostka } func vykresli() { print("\n \n \n \n \n \n \n \n") print("-------------- Aréna -------------- \n") print("Zdraví bojovníků: \n") print("\(bojovnik1) \(bojovnik1.grafickyZivot())") print("\(bojovnik2) \(bojovnik2.grafickyZivot())") } private func vypisZpravu(_ zprava: String) { print(zprava) sleep(1) } func zapas() { // původní pořadí var b1 = bojovnik1 var b2 = bojovnik2 print("Vítejte v aréně!") print("Dnes se utkají \(bojovnik1) s \(bojovnik2)! \n") // prohození bojovníků let zacinaBojovnik2 = kostka.hod() <= kostka.vratPocetSten() / 2 if (zacinaBojovnik2) { b1 = bojovnik2 b2 = bojovnik1 } print("Začínat bude bojovník \(b1)! \nZápas může začít...") _ = readLine() // cyklus s bojem while b1.nazivu() && b2.nazivu() { b1.utoc(souper: b2) vykresli() vypisZpravu(b1.vratPosledniZpravu()) // zpráva o útoku vypisZpravu(b2.vratPosledniZpravu()) // zpráva o obraně if (b2.nazivu()) { b2.utoc(souper: b1) vykresli() vypisZpravu(b2.vratPosledniZpravu()) // zpráva o útoku vypisZpravu(b1.vratPosledniZpravu()) // zpráva o obraně } print(" ") } } } {/SWIFT}
{SWIFT} // vytvoření objektů let kostka = Kostka(pocetSten: 10) let zalgoren = Bojovnik(jmeno: "Zalgoren", zivot: 100, utok: 20, obrana: 10, kostka: kostka) let gandalf : Bojovnik = Mag(jmeno: "Gandalf", zivot: 60, utok: 15, obrana: 12, kostka: kostka, mana: 30, magickyUtok: 45) let arena = Arena(bojovnik1: zalgoren, bojovnik2: gandalf, kostka: kostka) // zápas arena.zapas() {/SWIFT}
{SWIFT} class Kostka : CustomStringConvertible { var description: String { return "Kostka s \(pocetSten) stěnami" } private var pocetSten : Int init() { pocetSten = 6 } init(pocetSten: Int) { self.pocetSten = pocetSten } func vratPocetSten() -> Int { return pocetSten } func hod() -> Int { return Int(arc4random_uniform(UInt32(pocetSten))) + 1 } } {/SWIFT}
Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.
Opäť vidíme, ako môžeme znovupoužívat kód. S dedičnosťou je spojené naozaj mnoho techník, ako si ušetriť prácu. V našom prípade to ušetrí niekoľko riadkov, ale u väčšieho projektu by to mohlo mať obrovský význam.
Aplikácia teraz funguje tak, ako má.
-------------- Aréna -------------- Zdraví bojovníků: Zalgoren [############# ] Gandalf [################# ] Gandalf použil magii za 52 hp Zalgoren utrpěl poškození 36 hp
Aréna nás však neinformuje o mane mága, poďme to napraviť. Pridáme
mágovi verejnú metódu grafickaMana()
, ktorá bude obdobne ako u
života vracať String
s grafickým ukazovateľom many.
Aby sme nemuseli logiku so zložením ukazovatele písať dvakrát, upravíme
metódu grafickyZivot()
v Bojovnik.swift
. Pripomeňme
si, ako vyzerá:
func grafickyZivot() -> String { var s = "[" let celkem : Double = 20 var pocet : Double = round((zivot / maxZivot) * celkem) if (pocet == 0) && (nazivu()) { pocet = 1; } for _ in 0..<Int(pocet) { s += "#" } s = s.padding(toLength: Int(celkem) + 1, withPad: " ", startingAt: 0) s += "]" return s }
Vidíme, že nie je výnimkou premenných zivot
a
maxZivot
na živote nijako závislá. Metódu premenujeme na
grafickyUkazatel()
a dáme ju 2 parametre: aktuálnu hodnotu a
maximálnu hodnotu. Premenné zivot
a maxZivot
v tele
metódy potom nahradíme za aktualni
a maximalni
.
Modifikátor bude fileprivate
, aby sme metódu mohli v potomkovi
použiť:
fileprivate func grafickyUkazatel(aktualni: Double, maximalni: Double) -> String { var s = "[" let celkem : Double = 20 var pocet : Double = round((aktualni / maximalni) * celkem) if (pocet == 0) && (nazivu()) { pocet = 1; } for _ in 0..<Int(pocet) { s += "#" } s = s.padding(toLength: Int(celkem) + 1, withPad: " ", startingAt: 0) s += "]" return s }
Metódu grafickyZivot()
v triede Bojovnik
naimplementujeme znovu, bude nám v nej stačiť jediný riadok a to zavolanie
metódy grafickyUkazatel()
s príslušnými parametrami:
func grafickyZivot() -> String { return grafickyUkazatel(aktualni: zivot, maximalni: maxZivot) }
Určite som mohol v tutoriálu s bojovníkom urobiť metódu
grafickyUkazatel()
rovno. Chcel som však, aby sme si ukázali, ako
sa rieši prípady, keď potrebujeme vykonať podobnú funkčnosť viackrát. S
takouto parametrizáciou sa v praxi budete stretávať často, pretože nikdy
presne nevieme, čo budeme v budúcnosti od nášho programu požadovať.
Teraz môžeme vykresľovať ukazovateľ tak, ako sa nám to hodí. Presuňme
sa do triedy Mag
a naimplementujme metódu
grafickaMana()
:
func grafickaMana() -> String { return grafickyUkazatel(aktualni: mana, maximalni: maxMana) }
Jednoduché, že? Teraz je mág hotový, zostáva len naučiť arénu
zobrazovať manu v prípade, že je bojovník mág. Presuňme sa teda do
Arena.swift
.
Rozpoznanie typu objektu
Keďže sa nám teraz vykreslenie bojovníka skomplikovalo, urobíme si na
neho samostatnú metódu vypisBojovnika()
, jej parametrom bude
daná inštancie bojovníka:
func vypisBojovnika(_ b: Bojovnik) { print(b) print("Život:", terminator: " ") print(b.grafickyZivot()) }
Teraz poďme reagovať na to, či je bojovník mág. Minule sme si povedali,
že k tomu slúži operátor is
:
func vypisBojovnika(_ b: Bojovnik) { print(b) print("Život:", terminator: " ") print(b.grafickyZivot()) if b is Mag { print("Mana:", terminator: " ") print((b as! Mag).grafickaMana()) } }
Bojovníka sme museli na mága pretypovať pomocou operátora
as
, aby sme sa k metóde grafickaMana()
dostali.
Samotný Bojovnik
ju totiž nemá. Zas tu máme výkričník známy
z Optional
. Funguje tu veľmi podobne. Keby premenná
b
nebola na pozadí typu Mag
, tak program spadne. My
sa ale najskôr pýtame pomocou is
, či Mag
je a až
potom vykonáme vynútené pretypovanie. Mohli by sme použiť ?
,
Ktorý by vrátil Optional
a my mohli výsledok pretypovania
spracovať bezpečne. Tu to ale nie je nutné a ani vhodné.
To by sme mali, vypisBojovnika()
budeme volať v metóde
vykresli()
, ktorá bude vyzerať takto:
- App
- Arena.swift
- Bojovnik.swift
- main.swift
- Kostka.swift
{SWIFT} class Arena { private var bojovnik1 : Bojovnik private var bojovnik2 : Bojovnik private var kostka : Kostka init(bojovnik1: Bojovnik, bojovnik2: Bojovnik, kostka: Kostka) { self.bojovnik1 = bojovnik1 self.bojovnik2 = bojovnik2 self.kostka = kostka } func vykresli() { print("\n \n \n \n \n \n \n \n") print("-------------- Aréna -------------- \n") print("Zdraví bojovníků: \n") vypisBojovnika(bojovnik1) print(" ") vypisBojovnika(bojovnik2) } private func vypisZpravu(_ zprava: String) { print(zprava) sleep(1) } func zapas() { // původní pořadí var b1 = bojovnik1 var b2 = bojovnik2 print("Vítejte v aréně!") print("Dnes se utkají \(bojovnik1) s \(bojovnik2)! \n") // prohození bojovníků let zacinaBojovnik2 = kostka.hod() <= kostka.vratPocetSten() / 2 if (zacinaBojovnik2) { b1 = bojovnik2 b2 = bojovnik1 } print("Začínat bude bojovník \(b1)! \nZápas může začít...") _ = readLine() // cyklus s bojem while b1.nazivu() && b2.nazivu() { b1.utoc(souper: b2) vykresli() vypisZpravu(b1.vratPosledniZpravu()) // zpráva o útoku vypisZpravu(b2.vratPosledniZpravu()) // zpráva o obraně if (b2.nazivu()) { b2.utoc(souper: b1) vykresli() vypisZpravu(b2.vratPosledniZpravu()) // zpráva o útoku vypisZpravu(b1.vratPosledniZpravu()) // zpráva o obraně } print(" ") } } func vypisBojovnika(_ b: Bojovnik) { print(b) print("Život:", terminator: " ") print(b.grafickyZivot()) if b is Mag { print("Mana:", terminator: " ") print((b as! Mag).grafickaMana()) } } } {/SWIFT}
{SWIFT} class Bojovnik: CustomStringConvertible { fileprivate var jmeno : String fileprivate var zivot : Double fileprivate var maxZivot : Double fileprivate var utok : Int fileprivate var obrana : Int fileprivate var kostka : Kostka private var zprava : String = "" init(jmeno: String, zivot: Int, utok: Int, obrana: Int, kostka: Kostka) { self.jmeno = jmeno self.zivot = Double(zivot) self.maxZivot = self.zivot self.utok = utok self.obrana = obrana self.kostka = kostka } convenience init() { self.init(jmeno: "Standardní válečník", zivot: 100, utok: 20, obrana: 10, kostka: Kostka()) } var description: String { return jmeno } func nazivu() -> Bool { return zivot > 0 } fileprivate func grafickyUkazatel(aktualni: Double, maximalni: Double) -> String { var s = "[" let celkem : Double = 20 var pocet : Double = round((aktualni / maximalni) * celkem) if (pocet == 0) && (nazivu()) { pocet = 1; } for _ in 0..<Int(pocet) { s += "#" } s = s.padding(toLength: Int(celkem) + 1, withPad: " ", startingAt: 0) s += "]" return s } func grafickyZivot() -> String { return grafickyUkazatel(aktualni: zivot, maximalni: maxZivot) } func utoc(souper: Bojovnik) { let uder = utok + kostka.hod() nastavZpravu("\(jmeno) útočí s úderem za \(uder) hp") souper.branSe(uder: uder) } func branSe(uder: Int) { let zraneni = Double(uder - (obrana + kostka.hod())) var zprava = "" if (zraneni > 0) { zivot -= zraneni zprava = "\(jmeno) utrpěl poškození \(Int(zraneni)) hp" if (zivot <= 0) { zivot = 0 } } else { zprava = "\(jmeno) odrazil útok" } nastavZpravu(zprava) } fileprivate func nastavZpravu(_ zprava: String) { self.zprava = zprava } func vratPosledniZpravu() -> String { return zprava } } class Mag: Bojovnik { private var mana : Double private var maxMana : Double private var magickyUtok : Int init(jmeno: String, zivot: Int, utok: Int, obrana: Int, kostka: Kostka, mana: Int, magickyUtok: Int) { self.mana = Double(mana) self.maxMana = self.mana self.magickyUtok = magickyUtok super.init(jmeno: jmeno, zivot: zivot, utok: utok, obrana: obrana, kostka: kostka) } override func utoc(souper: Bojovnik) { var uder = 0 // Mana není naplněna if mana < maxMana { mana += 10; if (mana > maxMana) { mana = maxMana } super.utoc(souper: souper) nastavZpravu("\(jmeno) útočí s úderem za \(uder) hp") } else { // Magický útok uder = magickyUtok + kostka.hod() nastavZpravu("\(jmeno) použil magii za \(uder) hp") mana = 0 } souper.branSe(uder: uder) } func grafickaMana() -> String { return grafickyUkazatel(aktualni: mana, maximalni: maxMana) } } {/SWIFT}
{SWIFT} // vytvoření objektů let kostka = Kostka(pocetSten: 10) let zalgoren = Bojovnik(jmeno: "Zalgoren", zivot: 100, utok: 20, obrana: 10, kostka: kostka) let gandalf : Bojovnik = Mag(jmeno: "Gandalf", zivot: 60, utok: 15, obrana: 12, kostka: kostka, mana: 30, magickyUtok: 45) let arena = Arena(bojovnik1: zalgoren, bojovnik2: gandalf, kostka: kostka) // zápas arena.zapas() {/SWIFT}
{SWIFT} class Kostka : CustomStringConvertible { var description: String { return "Kostka s \(pocetSten) stěnami" } private var pocetSten : Int init() { pocetSten = 6 } init(pocetSten: Int) { self.pocetSten = pocetSten } func vratPocetSten() -> Int { return pocetSten } func hod() -> Int { return Int(arc4random_uniform(UInt32(pocetSten))) + 1 } } {/SWIFT}
Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.
Hotovo
-------------- Aréna -------------- Zdraví bojovníků: Zalgoren Život: [########## ] Gandalf Život: [##### ] Mana: [############# ] Zalgoren útočí s úderem za 28 hp
Ak ste niečomu nerozumeli, skúste si článok prečítať viackrát alebo pomalšie, sú to dôležité praktiky. V budúcej lekcii, Riešené úlohy k 5.-8. lekciu OOP vo Swift , si vysvetlíme pojem statika.
V nasledujúcom cvičení, Riešené úlohy k 5.-8. lekciu OOP vo Swift, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 8x (26.19 kB)