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ů.