dziedziczenie oparte na prototypach a dziedziczenie oparte na klasach

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 oddzielne pojęcia. Aby wykonać dziedziczenie, musisz użyć klasy bazowej, aby utworzyć nową klasę, która następnie może zostać użyta do wytworzenia pochodnych instancji.

Dlaczego JavaScript poszedł w tym kierunku (prototype-based object orientation)? jakie są zalety (i wady) prototypowego OO w stosunku do tradycyjnego, klasowego OO?

Author: Bardi Harborow, 2009-05-03

3 answers

Jest tu około stu zagadnień terminologicznych, głównie zbudowanych wokół kogoś (nie Ciebie) starającego się, aby ich pomysł brzmiał jak najlepszy.

Wszystkie języki obiektowe muszą być w stanie poradzić sobie z kilkoma pojęciami:

  1. enkapsulacja danych wraz z powiązanymi operacjami na danych, między innymi jako członkowie danych i funkcje Członkowskie lub jako dane i metody.
  2. dziedziczenie, umiejętność mówienia, że te obiekty są właśnie takie inne zbiory obiektów z wyjątkiem tych zmian
  3. polimorfizm ("wiele kształtów"), w którym obiekt sam decyduje o tym, jakie metody mają być uruchomione, dzięki czemu można polegać na języku, aby poprawnie kierować żądania.

Teraz, jeśli chodzi o porównanie:

Pierwszą rzeczą jest całe pytanie "Klasa" vs "prototyp". Idea pierwotnie rozpoczęła się w Simula, gdzie za pomocą metody opartej na klasach każda klasa reprezentowała zbiór obiektów, które dzieliły tę samą przestrzeń Stanów (Czytaj " możliwe wartości") i tych samych operacji, tworząc tym samym klasę równoważności. Jeśli spojrzysz wstecz na Smalltalk, ponieważ możesz otworzyć klasę i dodać metody, jest to skutecznie takie samo, jak to, co możesz zrobić w Javascript.

Później języki OO chciały używać statycznego sprawdzania typów, więc otrzymaliśmy pojęcie stałego zestawu klas w czasie kompilacji. W wersji open-class miałeś większą elastyczność; w nowszej wersji miałeś możliwość sprawdzenia pewnych rodzajów poprawności w kompilatorze, który w przeciwnym razie wymagałyby testów.

W języku" opartym na klasach " 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. Abstrakcyjnie jednak klasa jest klasą równoważności wszystkich obiektów, które mają tę samą przestrzeń stanów i metody. Kiedy dodajesz metodę do prototypu, skutecznie tworzysz element nowej klasy równoważności.

Dlaczego to robisz? przede wszystkim dlatego, że tworzy prosty, logiczny, elegancki mechanizm w czasie uruchamiania. teraz, aby utworzyć nowy obiekt, lub , aby utworzyć nową klasę, musisz po prostu wykonać głęboką kopię, kopiując wszystkie dane i prototypową strukturę danych. Dziedziczenie i polimorfizm otrzymujesz mniej więcej za darmo wtedy: method lookup zawsze polega na zapytaniu słownika o implementację metody po nazwie.

Powodem, który znalazł się w skrypcie Javascript / ECMA jest w zasadzie to, że gdy zaczynaliśmy z tym 10 lat temu, mieliśmy do czynienia ze znacznie mniej wydajnymi komputerami i znacznie mniej zaawansowanymi przeglądarkami. Wybór metody opartej na prototypach oznaczał, że interpreter może być bardzo prosty przy zachowaniu pożądanych właściwości orientacji obiektu.

 174
Author: Charlie Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-19 17:19:47

Porównanie, które jest nieco stronnicze w stosunku do podejścia opartego na prototypach, można znaleźć w artykule - Self: the power of simplicity . W artykule przedstawiono następujące argumenty na rzecz prototypów:

Tworzenie przez kopiowanie . Tworzenie nowych obiektów z prototypów odbywa się poprzez prosta operacja, kopiowanie, z prostą biologiczną metaforą, klonowanie. Tworzenie nowe obiekty z klas są realizowane przez instancję, która obejmuje interpretacja Formatuj informacje w klasie. Instancjacja jest podobne do budowy domu z planu. Kopiowanie przemawia do nas jako prostsza metafora niż instancja.

Przykłady istniejących modułów . Prototypy są bardziej konkretne niż klasy ponieważ są to przykłady obiektów, a nie opisy formatowania i inicjalizacji. Te przykłady mogą pomóc użytkownikom w ponownym użyciu modułów, ułatwiając ich Rozumiem. System oparty na prototypie pozwala użytkownikowi na zbadanie typowego reprezentacyjne zamiast wymagać od niego, by zrozumiał jego opis.

Wsparcie dla obiektów jedyne w swoim rodzaju . Self zapewnia ramy, które mogą łatwo dołączaj jedyne w swoim rodzaju obiekty o własnym zachowaniu. Ponieważ każdy obiekt ma nazwane gniazda i gniazda mogą przechowywać stan lub zachowanie, każdy obiekt może mieć unikalne gniazda albo zachowania. Systemy klasowe są przeznaczone do sytuacji, w których istnieje wiele obiektów o tym samym zachowaniu. Nie ma wsparcia językowego dla obiekt posiadanie własnego, unikalnego zachowania i jest niewygodne (myśl wzorzec Singletona ), aby stworzyć klasę, która ma zagwarantowaną tylko jedną instancję. Ja nie cierpi z powodu żadnej z tych wad. Każdy obiekt można dostosować za pomocą własnego zachowania. Unikalny obiekt może przytrzymaj unikalne zachowanie, a oddzielna "instancja" nie jest potrzebna.

Eliminacja meta-regresu . Żaden obiekt w systemie klasowym nie może być samowystarczalny; inny obiekt (jego klasa) jest potrzebny do wyraź swoją strukturę i zachowanie. Prowadzi to do pojęciowo nieskończonego meta-regresu: a point jest instancją klasy Point, która jest instancją metametaclass Point, która jest instancją metametaclass Point, ad infinitum. Z drugiej strony, w systemach opartych na prototypach obiekt może zawierać własne zachowanie; żaden inny obiekt nie jest potrzebny, aby tchnąć w niego życie. Prototypy wyeliminuj meta-regres.

Self jest prawdopodobnie pierwszym językiem implementującym prototypy. (To także był pionierem innych ciekawych technologii, takich jak JIT, który później trafił do JVM. Więc czytanie innych artykułów powinno być również pouczające).

 38
Author: Vijay Mathew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-13 11:50:07

Powinieneś sprawdzić świetną książkę o JavaScript autorstwa Douglasa Crockforda . Zawiera bardzo dobre wyjaśnienie niektórych decyzji projektowych podejmowanych przez twórców JavaScript.

Jednym z ważnych aspektów projektowania JavaScript jest jego prototypowy system dziedziczenia. Obiekty są pierwszorzędnymi obywatelami w JavaScript, do tego stopnia, że regularne funkcje są również implementowane jako obiekty (dokładniej obiekt' Function'). Moim zdaniem, kiedy pierwotnie został zaprojektowany do pracy w przeglądarce miał być używany do tworzenia wielu pojedynczych obiektów. W przeglądarce DOM znajdują się takie okno, dokument itp. wszystkie obiekty singleton. Również JavaScript jest luźno typowanym językiem dynamicznym (W przeciwieństwie do Pythona, który jest silnie typowanym, dynamicznym językiem), w wyniku czego zaimplementowano koncepcję rozszerzenia obiektu poprzez użycie właściwości "prototype".

Więc myślę, że są pewne plusy dla OO opartych na prototypach zaimplementowanych w JavaScript:

  1. odpowiedni w środowiskach luźno typowanych nie ma potrzeby definiowania typów jawnych.
  2. sprawia, że niezwykle łatwo jest zaimplementować wzorzec Singletona(porównaj JavaScript i Javę w tym zakresie ,a będziesz wiedział, o czym mówię).
  3. dostarcza sposobów zastosowania metody obiektu w kontekście innego obiektu, dynamicznego dodawania i zastępowania metod z obiektu itd. (rzeczy, które nie są możliwe w mocno wpisanym języku).

Oto kilka minusów prototypowy OO:

  1. brak łatwego sposobu implementacji zmiennych prywatnych. Możliwe jest zaimplementowanie prywatnych zmiennych przy użyciu Kreatora Crockford przy użyciu closures , ale na pewno nie jest tak trywialne, jak użycie prywatnych zmiennych w Javie lub C#.
  2. Nie wiem jeszcze, jak zaimplementować wiele dziedziczeń (o ile jest to warte) w JavaScript.
 22
Author: Amit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-07 12:05:43