If you're seeing this message, it means we're having trouble loading external resources on our website.

Pokud používáš webový filtr, ujisti se, že domény: *.kastatic.org and *.kasandbox.org jsou vyloučeny z filtrování.

Hlavní obsah

Shrnutí: Objektově orientovaný design

Zde je přehled toho, co jsme probrali v lekci o objektově orientovaném programování.
Když programujeme, často zjišťujeme, že chceme vytvořit mnoho různých objektů, které mají podobné vlastnosti - například mnoho koček, které mají mírně odlišnou barvu a velikost, nebo mnoho tlačítek s různými popisky a pozicemi. Chceme říct "takhle obecně kočka vypadá" a pak řekneme "udělejme tuto konkrétní kočku, a tuto jinou kočku, která bude v několika ohledech podobná, a v jiných odlišná." V takovém případě chceme použít objektově orientovaný design pro definování typů objektů a vytvoření nových instancí těchto objektů.
Pro definování typu objektu v JavaScriptu musíme nejprve definovat "konstruktor". To je funkce, kterou použijeme, když chceme vytvořit novou instanci určitého typu objektu. Tady je konstruktor pro typ objektu Book:
var Book = function(title, author, numPages) {
  this.title = title;
  this.author = author;
  this.numPages = numPages;
  this.currentPage = 0;
};
Tato funkce má jako argumenty aspekty objektu, které budou rozdílné pro každou knihu - název, autor a počet stránek. Poté nastaví počáteční vlastnosti objektu na základě těchto argumentů, pomocí klíčového slova this. Pokud použijeme this v rámci objektu, odkazujeme se na aktuální instanci objektu, tedy odkaz na sebe sama. Vlastnosti musíme uložit do this, abychom je později mohli používat.
Chceme-li vytvořit instanci objektu Book, vyhlašujeme novou proměnnou pro její uložení, pak použijeme klíčové slovo new, následované názvem konstruktoru a předáme argumenty, které konstruktor očekává:
var book = new Book("Robot Dreams", "Isaac Asimov", 320);
Pak můžeme přistupovat k vlastnostem, které jsme uložili v objektu pomocí tečkové notace:
println("Líbilo se mi číst " + book.title); // Líbilo se mi číst Robot Dreams
println(book.author + " je můj nejoblíbenější autor"); // "Isaac Asimov"  je můj nejoblíbenější autor
Na druhou stranu, zde je ukázka toho, co by se stalo, pokud bychom nenastavili konstruktor správně:
var Book = function(title, author, numPages) {
};
var book = new Book("Little Brother", "Cory Doctorow", 380);
println("Líbilo se mi číst " + book.title); // Líbilo se mi číst undefined
println(book.author + "  je můj nejoblíbenější autor"); // undefined  je můj nejoblíbenější autor
Pokud předáme argumenty konstruktoru, ale neukládáme je pomocí this, pak k nim nelze mít přístup později! Objekt na ně zapomene.
Když definujeme objekty, často chceme spojit vlastnosti a chování objektu - všechny naše objekty koček by měly být schopny mňoukat() a jíst(). Takže musíme být schopni připojit funkce k definicím typu objektu, a můžeme to udělat tak, že je definujeme na tom, co se nazývá prototyp objektu:
Book.prototype.readItAll = function() {
  this.currentPage = this.numPages;
  println("Už máš přečteno " + this.numPages + " stránek!");
};
Je to podobné, jako kdybychom vytvářeli normální funkci, kromě toho, že ji zavěsíme na prototyp Book, namísto abychom ji definovali globálně. Takto JavaScript pozná, že tato funkce může být volána na jakémkoliv objektu Book, a že tato funkce má přístup k this knihy, na kterou je volána.
Pak můžeme zavolat funkci (kterou nazýváme metodou, pokud je připojena k objektu), například takto:
var book = new Book("Animal Farm", "George Orwell", 112);
book.readItAll(); // Už máš přečteno 112 stránek!
Pamatuj, že celý smysl objektově orientovaného designu je snadnější vytváření více souvisejících objektů (instance objektů). Podívejme se, jak to vypadá v kódu:
var pirate = new Book("Pirate Cinema", "Cory Doctorow", 384);
var giver = new Book("The Giver", "Lois Lowry", 179);
var tuck = new Book("Tuck Everlasting", "Natalie Babbit", 144);

pirate.readItAll(); // Už máš přečteno 384 stránek!
giver.readItAll(); // Už máš přečteno 179 stránek!
tuck.readItAll(); // Už máš přečteno 144 stránek!
Tento kód vytvoří tři knihy, které jsou podobné - mají stejné vlastnosti a chování, ale zároveň se i liší. Super!
Ve skutečném světě jsou kočky a psi různé typy objektů. Takže při programování Kočky a Psa zřejmě vytvoříš rozdílné typy objektů. Kočka bude mňoukat() a pes štěkat(). Ale zároveň budou tyto objekty podobné - oba objekty budou jíst(), budou mít věk, datum narození a datum úmrtí. Kočka i pes jsou savci, mají tedy hodně společného, i když se také zároveň odlišují.
V takovém případě chceme použít myšlenku dědičnosti objektů. Typ objektu by mohl dědit vlastnosti a chování podle typu nadřazeného objektu, ale zároveň má také své vlastní unikátní prvky. Všechny Kočky a Psi by mohli dědit z objektu Savci, takže bychom pro ně nemuseli znovu vynálézat jezení(). Jak bychom to udělali v JavaScriptu?
Vraťme se k našemu příkladu s knihou, a řekněme, že Book je objekt typu "rodič" (anglicky "Parent"), ze kterého mají dědit dva objekty - PaperBack a EBook.
Paperback, neboli brožovaná kniha, je typ knihy, který se od standardní knihy liší jednou věcí, minimálně v rámci našeho programu: má obrázek na přebalu (tzv. cover). Tím pádem náš konstruktor musí převzít čtyři argumenty (název, autor, počet stran, obálka):
var PaperBack = function(title, author, numPages, cover) {
  // ...
}
Protože se nám nechce znovu dělat všechnu tu práci, kterou jsme dělali při vytváření konstruktoru Book a jeho tří argumentů - využijeme toho, že tato část kódu je stejná. Takže můžeme zavolat konstruktor Book z konstruktoru PaperBack, a předat mu tyto argumenty:
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  // ...
};
Stále však musíme uložit i vlastnost cover, tedy přidat jeden řádek kódu:
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  this.cover = cover;
};
Nyní máme konstruktor pro PaperBack, který sdílí stejné vlastnosti jako Book, ale také chceme, aby PaperBack zdědil jeho metody. Zde je způsob, jak říci programu, že by prototyp PaperBack měl být založen na prototypu Book:
PaperBack.prototype = Object.create(Book.prototype);
Mohli bychom také chtít připojit chování typické pro paperback, jako je jeho hořlavost, a můžeme to tak udělat definováním funkcí prototypu. Tento kód pak napíšeme za kód, který jsme si uvedli výše:
PaperBack.prototype.burn = function() {
  println("Jejda, bylo spáleno " + this.numPages + " stránek");
  this.numPages = 0;
};
Takže nyní můžeme vytvořit nový paperback, přečíst si ho a pak ho spálit!
var calvin = new PaperBack("The Essential Calvin & Hobbes", "Bill Watterson", 256, "http://ecx.images-amazon.com/images/I/61M41hxr0zL.jpg");

calvin.readItAll(); // Už máš přečteno 256 stránek!
calvin.burn(); // Jejda, bylo spáleno 256 stránek!
(I když, pálit ji ve skutečnosti nebudeme, je to skvělá kniha. Ledaže bychom uvízli v ledové pustině, mrzli bychom a umírali.)
Nyní víš, jak používat objektově orientovaný design v JavaScriptu pro vytváření složitějších dat pro své programy a přitom tyto programy tvořit jednodušeji.