W JavaScript każdy obiekt jest jednocześnie instancją i klasą. Aby wykonać dziedziczenie, możesz użyć dowolnej instancji obiektu jako prototypu.
W Pythonie, C ++ itp. Istnieją klasy i instancje jako osobne pojęcia. Aby wykonać dziedziczenie, musisz użyć klasy podstawowej, aby utworzyć nową klasę, której można następnie użyć do utworzenia instancji pochodnych.
Dlaczego JavaScript poszedł w tym kierunku (orientacja obiektowa oparta na prototypach)? jakie są zalety (i wady) OO opartego na prototypach w porównaniu z tradycyjnym OO opartym na klasach?
javascript
oop
inheritance
prototype-programming
Stefano Borini
źródło
źródło
GEB
?Odpowiedzi:
Jest tu około stu zagadnień terminologicznych, głównie wokół kogoś (nie ciebie), który stara się, aby ich pomysł brzmiał jak najlepszy.
Wszystkie języki obiektowe muszą być w stanie poradzić sobie z kilkoma pojęciami:
Teraz, jeśli chodzi o porównanie:
Pierwszą rzeczą jest całe pytanie „klasa” kontra „prototyp”. Pomysł pierwotnie rozpoczął się w Simula, gdzie za pomocą metody opartej na klasach każda klasa reprezentowała zestaw obiektów, które dzieliły tę samą przestrzeń stanu (czytaj „możliwe wartości”) i te same operacje, tworząc w ten sposób klasę równoważności. Jeśli spojrzysz wstecz na Smalltalk, ponieważ możesz otworzyć klasę i dodać metody, jest to faktycznie to samo, co możesz zrobić w JavaScript.
Później języki OO chciały mieć możliwość statycznego sprawdzania typów, więc otrzymaliśmy pojęcie ustalonego zestawu klas w czasie kompilacji. W wersji otwartej miałeś większą elastyczność; w nowszej wersji można było sprawdzić niektóre rodzaje poprawności w kompilatorze, które w innym przypadku wymagałyby testowania.
W języku „klasowym” kopiowanie odbywa się w czasie kompilacji. W języku prototypowym operacje są przechowywane w prototypowej strukturze danych, która jest kopiowana i modyfikowana w czasie wykonywania. Jednak abstrakcyjnie klasa jest nadal klasą równoważności wszystkich obiektów, które mają tę samą przestrzeń stanu i metody. Dodając metodę do prototypu, skutecznie tworzysz element nowej klasy równoważności.
Dlaczego to robisz? przede wszystkim dlatego, że tworzy prosty, logiczny i elegancki mechanizm w czasie wykonywania. teraz, aby utworzyć nowy obiekt lub nową klasę, wystarczy wykonać głęboką kopię, kopiując wszystkie dane i prototypową strukturę danych. Otrzymujesz dziedziczenie i polimorfizm mniej więcej za darmo: wyszukiwanie metody zawsze polega na pytaniu słownika o implementację metody według nazwy.
Powodem, dla którego skończyło się skryptem JavaScript / ECMA, jest to, że kiedy zaczynaliśmy 10 lat temu, mieliśmy do czynienia ze znacznie słabszymi komputerami i znacznie mniej zaawansowanymi przeglądarkami. Wybór metody opartej na prototypach oznaczał, że interpreter może być bardzo prosty, zachowując pożądane właściwości orientacji obiektowej.
źródło
Porównanie, które jest nieco tendencyjne w stosunku do podejścia opartego na prototypach, można znaleźć w artykule Self: The Power of Simplicity . Artykuł przedstawia następujące argumenty za prototypami:
Self jest prawdopodobnie pierwszym językiem do implementacji prototypów (był także pionierem innych interesujących technologii, takich jak JIT, które później trafiły do JVM), więc czytanie innych dokumentów Self powinno być również pouczające.
źródło
point
jest instancją klasyPoint
, która jest instancją metaklasystandard-class
, która jest instancją samej siebie, ad finitum.Powinieneś sprawdzić świetną książkę o JavaScript autorstwa Douglasa Crockforda . Zapewnia bardzo dobre wyjaśnienie niektórych decyzji projektowych podjętych przez twórców JavaScript.
Jednym z ważnych aspektów projektowania JavaScript jest prototypowy system dziedziczenia. Obiekty są pierwszorzędnymi obywatelami JavaScript, do tego stopnia, że zwykłe funkcje są również implementowane jako obiekty (a dokładniej obiekt „Funkcja”). Moim zdaniem, kiedy pierwotnie został zaprojektowany do działania w przeglądarce, miał służyć do tworzenia wielu obiektów singletonowych. W przeglądarce DOM znajdziesz to okno, dokument itp. Wszystkie pojedyncze obiekty. JavaScript to także dynamiczny język luźno wpisany (w przeciwieństwie do silnie napisanego języka Python, język dynamiczny), w wyniku czego za pomocą właściwości „prototyp” zaimplementowano koncepcję rozszerzenia obiektu.
Myślę więc, że istnieją pewne zalety dla OO opartego na prototypach, zaimplementowanego w JavaScript:
Oto niektóre z wad prototypowego OO:
źródło