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

Jeżeli jesteś za filtrem sieci web, prosimy, upewnij się, że domeny *.kastatic.org i *.kasandbox.org są odblokowane.

Główna zawartość

Przegląd: Projektowanie zorientowane obiektowo

Poniżej jest podsumowanie tego, co już powiedzieliśmy na temat tworzenia oprogramowania obiektowego.
Kiedy tworzymy programy, często natrafiamy na sytuację w której chcemy stworzyć wiele podobnych do siebie obiektów- jak dużo kotów, które mają trochę inne rozmiary, kolory, albo wiele przycisków, z różnymi podpisami i rozmieszczeniem. Chcemy mieć możliwość by powiedzieć "to coś jest jak kot" a potem powiedzieć "zróbmy sobie kota jakiego chcemy, jeszcze jednego, i parę innych, a wszystkie będą do siebie jakoś tam podobne i jednocześnie różne od siebie". W tym wypadku, chcemy użyć techniki tworzenia programów zorientowanych obiektowo by zdefiniować typy obiektów i tworzyć nowe instancje tych obiektów.
By zdefiniować typ obiektu w JavaScripcie, musimy zdefiniować "funkcję konstruującą". To jest funkcja której użyjemy gdy będziemy chcieli stworzyć nowy obiekt tego konkretnego typu obiektów. Poniżej przedstawiam konstruktor obiektu typu Book:
var Book = function(title, author, numPages) {
this.title = title;
this.author = author;
this.numPages = numPages;
this.currentPage = 0;
};
Funkcja bierze argumenty dla aspektów, które podobnie jak różnice między książkami-mają je identyfikować -tytuł, autor, i ilość stron. Wtedy ustawia początkową właściwość obiektu bazowaną na tych własnościach, używając wyrażenia kluczowego this. Gdy używamy słowa kluczowego this w obiekcie, wtedy odwołujemy się do obecnej instancji tego obiektu: do niego samego. Własności przechowujemy w this by upewnić się, że będą pamiętane też później.
By stworzyć instancję obiektu Book, deklarujemy nową zmienną do przechowania go, a wtedy używamy wyrażenia new, za którym umieszczamy nazwę konstruktora funkcji, i przekazujemy argumenty których się konstruktor spodziewa:
var book = new Book("Robot Dreams", "Isaac Asimov", 320);
Możemy dobrać się do własności które przechowujemy w obiektach za pomocą kropki:
println("I loved reading " + book.title); // Uwielbiam ksiązkę Robot Dreams
println(book.author + " is my fav author"); // "Isaac Asimov" jest moim ulubionym autorem
A co jeśli byśmy źle zdefiniowali funkcję konstruktora?:
var Book = function(title, author, numPages) {
};
var book = new Book("Little Brother", "Cory Doctorow", 380);
println("I loved reading " + book.title); // Uwielbiam książkę undefined
println(book.author + " is my fav author"); // undefined jest moim ulubionym autorem
Jeżeli przekazujemy argumenty do konstruktora funkcji ale perfidnie nie określamy że przechowujemy je w this, wtedy nie będziemy mieli możliwości by się do nich później dobrać! Obiekt po prostu całkowicie o nich zapomni.
Kiedy definiujemy typy obiektów, często chcemy powiązać własności i zachowania ze sobą- tak jak nasze koty mogą robić miau() i jeść(). Potrzebujemy więc podpiąć funkcje to naszej definicji obiektu, i możemy to zrobić poprzez definiowanie ich na czymś co zwie się prototypem obiektu:
Book.prototype.readItAll = function() {
this.currentPage = this.numPages;
println("You read " + this.numPages + " pages!");
};
Dokładnie tak jak definiujemy funkcję normalnie, poza tym że ciągniemy to z prototypu Książki (Book) zamiast definiować globalnie. To pokazuje jak JavaScript wie że to jest funkcja która może być wywołana na jakiejkolwiek Książce(Book) , i że ta funkcja powinna móc się dobrać do this tej książki, na której jest wywołana.
Możemy wtedy wywołać funkcję (którą zwiemy tu metodą, gdyż jest podpięta do obiektu), w ten sposób:
var book = new Book("Animal Farm", "George Orwell", 112);
book.readItAll(); // You read 112 pages!
Całe ułatwienie programowania obiektowego to fakt, że możemy sobie zrobić wiele podobnych do siebie obiektów (instancji obiektów). Zobaczmy to w kodzie:
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(); // Przeczytałeś 384 strony!
giver.readItAll(); // Przeczytałeś 179 stron!
tuck.readItAll(); // Przeczytałeś 144 stron!
Ten kod daje nam trzy książki które są dość podobne do siebie - wszystkie mają te same własności i zachowania, ale są różne. Miodzio!
Jeśli teraz pomyślisz o naszym świecie, koty i psy są różnymi typami obiektów, więc prawdopodobnie stworzysz różne od siebie typy obiektów dla nich jeśli będziesz programować Koty i Psy. Kot będzie mógł robić swoje miau(), a pies będzie mógł szczekać(). Ale jednocześnie są podobne: i koty, i psy potrafią jeść(), oraz w obu przypadkach mają jakiś wiek, datęUrodzenia, i też dateŚmierci. Oba są ssakami, co oznacza że mają wiele z sobą wspólnego, nawet gdy są równocześnie różne.
W tym wypadku, chcemy użyć koncepcji dziedziczenia obiektów. Typ obiektu może dziedziczyć własności i zachowania z typu obiektu rodzica, ale wtedy ma w dodatku do cech rodzica cechy własne (nowe). Wszystkie Koty i Psy dziedziczą po Ssakach, więc nie muszą uczyć się na nowo jak jeść() od podszewki. Jak to zrobić więc w JavaScripcie?
Wróćmy do naszego przykładu książki, i powiedzmy że Book (książka) jest "rodzicem" typu obiekty, i chcemy mieć dwa obiekty dziedziczące z niej- Papierek (Paperback) i Ebook.
Papierek (paperback ) jest jak książka, ale różni się od niej przynajmniej w naszym programie: ma obrazek na okładce. Nasz konstruktor więc potrzebuje pobierać cztery argumenty by przechować te dodatkowe informacje:
var PaperBack = function(title, author, numPages, cover) {
// ...
}
A teraz nie musimy robić wszystkiego co już mamy w konstruktorzeKsiążki (Book) by zapamiętać pierwsze trzy argumenty - chcemy skorzystać z faktu, że kod będzie dokładnie taki sam. Możemy więc powiedzieć konstruktorowi Książki (Book) by wywołał z konstuktora Papierka (PaperBack), i przekazał te argumenty dalej:
var PaperBack = function(title, author, numPages, cover) {
Book.call(this, title, author, numPages);
// ...
};
Wciąż potrzebujemy przetrzymywać własność cover (okładkę) w obiekcie, więc musimy napisać jeszcze jedną linijkę by sobie z tym poradzić:
var PaperBack = function(title, author, numPages, cover) {
Book.call(this, title, author, numPages);
this.cover = cover;
};
Mamy teraz konstruktor dla naszego PaperBack(papierka), który pomaga w dzieleniu tych samych właściwości co Books, ale chcemy by nasz papierek dziedziczył jego metody. Poniżej pokazano jak to zrobić, poprzez pokazanie programowi że prototyp Papierek (paperback) powinien być bazowany na prototypie Książka (Book):
PaperBack.prototype = Object.create(Book.prototype);
Możemy chcieć też dołączyć do papierka zachowanie, które tylko będzie on przejawiał, jak dla przykładu możliwość spalenia go: możemy tego dokonać poprzez definiowanie funkcji na prototypie. Po linii podanej wyżej dopisujemy:
PaperBack.prototype.burn = function() {
println("Omg, you burnt all " + this.numPages + " pages");
this.numPages = 0;
};
A teraz możemy stworzyć sobie nowy papierek, przeczytać go, i spalić!
var calvin = new PaperBack("The Essential Calvin & Hobbes", "Bill Watterson", 256, "http://ecx.images-amazon.com/images/I/61M41hxr0zL.jpg");

calvin.readItAll(); //Przeczytałeś 256 stron!
calvin.burn(); // Spaliłeś wszystkie 256 stron!
(Tak naprawdę to niczego nie będziemy palić, bo to fajna książka, no chyba że znajdziemy się na lodowcu i brak będzie nam źródła ciepła)
I teraz widzisz, że można tworzyć oprogramowanie obiektowe w JavaScripcie, które będzie mogło być coraz bardziej rozbudowane pod względem obliczeni i kodu-i prawdopodobnie sprawi, że nasz świat będzie lepszy.

Chcesz dołączyć do dyskusji?

Na razie brak głosów w dyskusji
Rozumiesz angielski? Kliknij tutaj, aby zobaczyć więcej dyskusji na angielskiej wersji strony Khan Academy.