Jsme zpět u našeho programu,
který vytváří Winstony.
Ale přidala jsem nový
typ objektu a to Hoppera.
Protože Hopper se cítil
trochu opomenutý.
Teď definuji Hoppera stejným
způsobem, jakým definuji Winstona.
Počínaje funkcí konstruktoru
a stejnými vlastnostmi.
Máme zde draw a talk...
A pak jsem také přidala
další metodu zvanou Horray.
Protože Hoppeři opravdu rádi
slaví a Winstoni zase ne.
Ve spodní části funkce jsem
vytvořila dva nové objekty Hoppera:
Little Hoppera a Big Hoppera.
Nakreslila jsem je a na jednoho
zavolala "talk" a na druhého "hooray".
Je to celkem povedené.
Když se ale podíváte na horní část kódu,
možná si všimnete něčeho zajímavého.
Kód pro Hoppera je velmi podobný
kódu pro Winstona.
Obzvláště se podívejte
na tento konstruktor.
Nevím, jestli si vzpomínáte,
ale tento kód vypadá úplně stejně
jako kód pro konstruktor Winstona.
Tato funkce talk je taky
definována úplně stejným kódem,
jako funkce talk u Winstona.
Oba mají také funkci draw.
Tyto dva typy objektů mají
tedy hodně společného.
A dává to smysl,
protože Hopper a Winston jsou v našem
světě dva velmi podobné typy objektů.
A pokud uvažujete o skutečném světě,
o tom mimo počítač,
většina typů objektů sdílí podobné rysy
s jinými typy objektů.
Například zvířecí říše.
Všechna zvířata jsou
v některých ohledech podobná.
A pak máme různé typy
zvířat, jako například lidi.
Lidé hodně podobností sdílejí, ale také
mají své vlastní jedinečné podobnosti.
Takže bychom mohli říct,
že zvíře je typ objektu,
od kterého typ lidského objektu
zdědil určitou funkčnost.
Nezačíname úplně od nuly.
Přidáváme k funkcionalitě,
kterou máme jako zvíře.
Stejně jako všechna zvířata
vydávají zvuky, tak lidé mají řeč.
Koncept dědičnosti objektu
je opravdu užitečný při programování.
Můžeme dokonce vytvořit řetězec
dědičnosti objektů v našem Javascriptu.
Abychom to provedli, musíme zjistit,
co naše typy objektů spolu sdílejí.
A musíme pro to
vymyslet nějaký název.
Protože se chystáme vytvořit
nový typ objektu,
který představuje základní objekt.
Nazvěme je creatures (tvorové).
Oba jsou totiž tvory.
Takže napíšeme:
var creature se rovná.
A nyní potřebujeme náš konstruktor.
Pojďme ho tedy ukrást Hopperovi,
protože je to to samé,
co má Winston.
Co chceme dělat dál?
Možná chceme přidat
funkci "talk".
Funkci talk bychom mohli
ukrást Hoppperovi.
Ale samozřejmě to musíme mít
v prototypu Creature.
Takže teď máme tento
typ objektu Creature.
Ale ještě musíme Hopperovi říct,
že Hopper by vlastně měl zakládat
svou funkčnost na základě Creature.
Můžeme to udělat napsáním
tohoto řádku zde.
Napíšeme: Hopper.prototype rovná
se object.create(creature.prototype);
Tento řádek říká, aby Javascript
založil Hopperův prototyp,
čili všechny jeho funkce,
na základě prototypu Creature.
To znamená, že pokaždé,
když hledá funkci pro Hoppera,
podívá se nejprve na Hopperův
prototyp a pokud ho nenajde,
podívá se, zda je součástí
prototypu Creature.
A to je to, čemu říkáme
prototypový řetězec.
Jakmile máme toto hotovo,
měli bychom být schopni smazat
funkci talk pro Hoppera,
protože ta již existuje
v rámci Creatura.
Je už v prototypovém řetězci,
tak to zkusíme.
Funguje to a to kvůli tomu,
že talk najdeme u prototypu Creature.
Zkusme to smazat
také u Winstona.
Nefungovalo to.
Máme hlášení, že objekt
nemá žádnou metodu talk.
Ale proč to tak je?
Máme náš konstruktor Winstona i
funkci draw a jenom jsme odebrali talk.
Všimnete si, že jsme zapomněli
říci prototopu Winstona,
že má být založen na základě
prototypu Creature.
Potřebujeme tedy přidat
velmi důležitý řádek:
Winston.prototype rovná se
Object.create(Creature.prototype);
Všimněte si něčeho důležitého.
Tento řádek máme až po
funkci konstruktoru,
ale předtím, než k prototypu Winstona
přidáme cokoli jiného.
Obvykle to chcete udělat tak,
že si nejdříve určíte,
jaký prototyp bude výchozí.
Poté k prototypu
přidáváte další věci.
Protože by mohly
existovat nějaké věci,
které jsou jedinečné pro Winstony
nebo jedinečné pro Hoppery.
Nejsou závislé na Creature.
A to je naprosto v pohodě,
můžete je definovat.
Teď, když se na to podíváme,
pořád se nám opakuje nějaký kód.
Kód konstruktoru.
Máme ho celkem třikrát.
Co kdybychom ho smazali,
pojďme to zkusit.
Dobře, vypadá to,
že to takhle nepůjde.
Náš Hopper se objevil
v levém horním rohu.
A všechno o sobě zapomněl.
To se stalo kvůli tomu,
že Javascript nepředpokládá,
že chcete stejný konstruktor,
i když na něm chcete založit prototyp.
To vám umožní definovat svůj vlastní
konstruktor pro tyto objekty.
Ale také vám to ulehčuje
volání konstruktoru z podobjektu.
Způsob, jakým to můžeme udělat,
je, že napíšeme:
Creature.call(this, nickname, age, x, y);
Dělá to to, že se zavolá funkce Creature,
konstrukční funkce, a řekne se:
Zavolejme si konstruktor funkce,
tak jako u objektu Hoppera.
A to přesně s těmi
samými argumenty.
To jsou argumenty,
které používáme u Hoppera.
A tím se provede tento kód,
jako by to bylo právě tady.
A přesně to chceme.
A fungovalo to.
Můžeme pokračovat a zkopírovat
tento řádek i do konstruktoru Winstona.
A funguje to.
Podívejte na to.
Shrnuli jsme všechny naše sdílené
vlastnosti a funkce o objektech,
do tohoto jediného a základního
typu objektu: Creature.
A vytvořili jsme dva typy objektů, které
jsou rozšířením tohoto základního objektu.
Zdědí nějakou funkčnost,
ale také přidávají své vlastní.
A opravdu skvělé je to,
že můžeme změnit sdílenou
funkčnost na jednom místě.
Kdybychom chtěli změnit věk,
stačilo by napsat: "+ years old".
Super, teď všichni mají
"years old" na konci.
Nebo bychom mohli
změnit funkci "talk".
A nyní Winstoni i Hoppeři
říkají "sup".
Takže teď jste viděli,
jak vytvářet typy objektů
a jak typu objektu dědit.
Můžete začít přemýšlet o tom,
jak by to mohlo být užitečné ve vašich
kresbách, animacích, simulacích a hrách.
Můžete mít třeba hru, která
obsahuje mnoho typů postav.
Všechny mohou běžet,
ale jen některé mohou skákat.
To je perfektní místo pro použití
typů objektů a jejich dědičnosti.
Vsadím se, že dokáže přijít
na hodně dalších příkladů.