Dlaczego wiele dynamicznych języków programowania typu kaczych stosuje podejście oparte na klasach zamiast OOP opartego na prototypach?

23

Ponieważ dość wiele dynamicznych języków programowania ma funkcję pisania kaczego , mogą też w dowolnym momencie otwierać i modyfikować metody klas lub instancji (takie jak Ruby i Python ), a następnie…

Pytanie 1) Jaka jest potrzeba zajęć w dynamicznym języku? Dlaczego język jest zaprojektowany w taki sposób, aby używać klasy jako pewnego rodzaju „szablonu” zamiast robić to prototypowo i po prostu używać obiektu?

JavaScript jest również oparty na prototypach, ale CoffeeScript (ulepszona wersja JavaScript) wybiera sposób oparty na klasach. Podobnie jest w przypadku Lua (oparty na prototypach) i MoonScript (oparty na klasach). Ponadto istnieje klasa w ES 6. Więc…

Pytanie 2) Czy sugeruje to, że jeśli spróbujesz ulepszyć język oparty na prototypach, między innymi powinieneś zmienić go na oparty na klasach? Jeśli nie, dlaczego jest tak zaprojektowany?

iceX
źródło
9
Wielu programistów nie chce, aby przeszkadzało im nauczenie się czegoś nowego. (To zbyt obce i „trudne”). Stąd wszystkie biblioteki klas i języki, które się do nich kompilują.
Thomas Eding
1
Zgadzam się z Thomasem, ale zabawne jest to, że po nauczeniu się dynamicznego podejścia jest to faktycznie łatwiejsze (nie trudniejsze). Pojęcie przedmiotów wciąż istnieje, po prostu można je zmieniać bez ponownej kompilacji jakiegoś głupiego „planu”. Jeśli chcę położyć 5. nogę na krześle, nie chcę najpierw zmieniać schematu, chcę tylko dodać nogę. Dynamiczne języki bardziej moim zdaniem modelują rzeczywistość.
Lonnie Best
1
OOP został wymyślony w kontekście typowanym statycznie, w którym typy muszą być deklarowane. Tam zajęcia są rozsądnym krokiem naprzód w stosunku do rekordów i modułów. Protokół OOP był zawsze interesującym tematem badawczym dla języka Self i jakimś sposobem przekształcił go w JavaScript jako najprostszy sposób na odznaczenie hasła „OOP” dla języka zasadniczo funkcjonalnego. Zaletą jest to, że można zaimplementować klasy na prototypach. Podczas gdy lubię metaobiekty, oddzielanie klas od ich instancji ułatwia pisanie dobrze ułożonego, prostego, luźno powiązanego kodu.
amon
3
Po pierwsze: sam JavaScript obsługuje classsłowo kluczowe od następnego standardu ECMAScript (ECMAScript 6). Obsługa klas w JavaScript była planowana od dłuższego czasu. Teraz to, co to jest - klasy to po prostu cukier składniowy, łatwiejszy do uzasadnienia na temat modelu dla obiektów tego samego typu. Tak jest w JS i tak jest w Pythonie i innych dynamicznych językach.
Benjamin Gruenbaum
1
@BenjaminGruenbaum „... klasy to po prostu cukier składniowy ...” wow, to dla mnie dość nowatorski pomysł, naprawdę, w przypadku języków takich jak ruby ​​i python wydaje się, że nie ma znaczenia, czy użyć obiektu, czy klasa jako szablon - i tak można oba modyfikować w locie. I tak naprawdę nie ma znaczenia, jak radzą sobie z dziedziczeniem. Może więc nie trzeba rozróżniać między podejściem klasowym a podejściem prototypowym dla dynamicznego języka :)
iceX

Odpowiedzi:

12

Pytanie 1) Jaka jest potrzeba zajęć w języku dynamicznym? Dlaczego język został zaprojektowany w taki sposób, aby używać klasy jako pewnego rodzaju „szablonu” zamiast robić to prototypowo i po prostu używać obiektu?

Pierwszy język OO (chociaż nie był nazywany „OO”), Simula, nie miał dziedzictwa. Dziedziczenie zostało dodane w Simula-67 i było oparte na klasach.

Mniej więcej w tym samym czasie Alan Kay zaczął pracować nad swoim pomysłem na nowy paradygmat programowania, który później nazwał „Object-Orientation”. Naprawdę lubił dziedzictwo i chciał mieć je w swoim języku, ale też bardzo nie lubił zajęć. Nie mógł jednak znaleźć sposobu na dziedziczenie bez klas, więc postanowił, że nie lubi klas bardziej niż spuściznę i zaprojektował pierwszą wersję Smalltalk, Smalltalk-72 bez klas, a więc bez dziedziczenia.

Kilka miesięcy później Dan Ingalls opracował projekt klas, w których same klasy były obiektami, a mianowicie instancjami metaklas. Alan Kay uznał ten projekt za nieco mniej atrakcyjny niż starsze, więc Smalltalk-74 został zaprojektowany z klasami i dziedziczeniem opartym na klasach.

Po Smalltalk-74 Alan Kay poczuł, że Smalltalk zmierza w złym kierunku i tak naprawdę nie reprezentuje tego, o co chodziło w OO, i zaproponował, aby zespół porzucił Smalltalk i zaczął świeżo, ale został przegłosowany. W ten sposób pojawiła się Smalltalk-76, Smalltalk-80 (pierwsza wersja Smalltalk, która zostanie wydana naukowcom), a wreszcie Smalltalk-80 V2.0 (pierwsza wersja, która zostanie wydana komercyjnie, i wersja, która stała się podstawą ANSI Smalltalk) .

Ponieważ Simula-67 i Smalltalk-80 są uważane za dziadków wszystkich języków OO, prawie wszystkie kolejne języki na ślepo skopiowały projekt klas i dziedziczenie oparte na klasach. Kilka lat później, kiedy inne idee, takie jak dziedziczenie oparte na mixinach zamiast klas, i delegowanie oparte na obiektach zamiast dziedziczenia na podstawie klas, pojawiło się już dziedziczenie oparte na klasach.

Co ciekawe, obecny język Alana Kay oparty jest na prototypowym przekazaniu.

Jörg W Mittag
źródło
„... obecny język Alana Kay'a…”, który jest…?
Javier
@Javier: Nie sądzę, że ma nazwę, a nazwa systemu ciągle się zmienia.
Jörg W Mittag
To powinna być dobra odpowiedź, aby wskazać, kiedy następnym razem ktoś wymienia dziedziczenie jako wymóg dla OO :)
Hej
1
@iceX: Alan Kay założył Viewpoints Research Institute, aby opracować swoje pomysły. Niestety informacje są naprawdę rozproszone na stronie internetowej.
Jörg W Mittag
3
Alan Kay zacytował OO: „OOP oznacza dla mnie tylko przesyłanie wiadomości, lokalne przechowywanie i ochronę oraz ukrywanie procesów państwowych oraz ekstremalne późne wiązanie wszystkich rzeczy. Można to zrobić w Smalltalk i LISP. Możliwe są też inne systemy co jest możliwe, ale nie jestem ich świadomy ”.
Joeri Sebrechts
23

Wielu programistów woli pracować z klasami. Jest to bardzo łatwa do zrozumienia koncepcja, która jest dobrym modelem procesów myślowych człowieka na temat świata (to znaczy instynktownie odnosimy rzeczywiste przedmioty do abstrakcyjnej grupy przedmiotów, do których uważamy, że należą, czyli do klasy) . Ponadto klasy ułatwiają rozumowanie na temat typów obiektów: w języku opartym na klasach stosowanie zasad takich jak podstawienie Liskowa jest prostsze niż w języku, w którym mamy tylko obiekty, które mogą mieć różne metody lub których typ może się nawet zmienić w czasie wykonywania , jak ma to miejsce w JavaScript.

Zauważ, że nawet w JavaScript ogromna ilość kodu po prostu używa narzędzia prototypowego do emulacji klas. Wynika to głównie z tego, że wielu programistów woli myśleć w ten sposób.

Istnieje również inny powód, dla którego preferowane są języki oparte na klasach: łatwiej jest je skompilować do wydajnego kodu. Najbardziej wydajne maszyny wirtualne JavaScript skutecznie dynamicznie tworzą klasy reprezentujące typy obiektów JavaScript wraz ze zmianą metod i prototypów. Zobacz ten opis implementacji V8, aby znaleźć uzasadnienie, dlaczego tak się dzieje.

Jules
źródło
4
Twój ostatni akapit w rzeczywistości popiera dokładne przeciwieństwo tego, co mówisz: V8 dowodzi, że nie potrzebujesz klas w języku, aby skompilować do wydajnego kodu opartego na klasach.
Jörg W Mittag
4
Tak, nie potrzebujesz ich - ale fakt, że V8 (i prawdopodobnie Self, chociaż nie przeczytałem zbyt wiele o konstrukcji tego systemu) skutecznie tworzy klasy wirtualne oznacza, że ​​począwszy od języka, który natywnie używa klas, jest prawie z pewnością łatwiejsze i dlatego prawdopodobnie JIT musiałby spędzać mniej czasu na kompilowaniu kodu.
Jules
11
Jasne, a fakt, że V8 skutecznie tworzy GOTOs i rejestry, oznacza, że ​​porzucenie wszystkich abstrakcji i pisanie bezpośrednio w asemblerze jest prawie na pewno łatwiejsze, i dlatego prawdopodobnie JIT musiałby spędzać mniej czasu na kompilowaniu kodu. Kompilator wspiera abstrakcje wyższego poziomu.
Jörg W Mittag
1
Tak, ale jest to kompromis, ponieważ abstrakcja wyższego poziomu jest w większości przypadków trudniejsza do zaimplementowania i często ma negatywny wpływ na wydajność w czasie wykonywania, szczególnie podczas pracy z JIT zamiast kompilatorem AOT. Podejrzewam, że wielu projektantów języków wybiera strukturę opartą na klasach z jednego lub obu tych powodów; Wiem, że dlatego wybrałem klasy ze stałymi elementami dla (inaczej dynamicznego) języka, nad którym pracuję, ale mogę jedynie spekulować na temat innych języków.
Jules
1
Twierdzę, że jedynym sposobem, w jaki programiści wolą „myśleć w klasach”, jest to, że tak uczy się większości z nas. Zdecydowanie pamiętam jednak wielu moich kolegów z college'u, którzy od kilku lat mieli problemy ze zrozumieniem niektórych naprawdę podstawowych koncepcji obiektowych. Z perspektywy czasu wydaje się to oczywiste i łatwe.
KChaloux
3

Słyszałem, że w dużych projektach, w których zespoły ludzi pracują razem nad tym samym kodem, elastyczne języki (w których można modyfikować właściwości i metody obiektu w czasie wykonywania) to wolności, których inni członkowie zespołu nie chcą mieć.

Chcąc wiedzieć, kiedy mają do czynienia z obiektem, chcą wiedzieć, że obiekt będzie działał tak, jak mówi plan, a nie w jakiś zmieniony sposób, w jaki inny ambitny programista postanowił go zmienić, aby wykonać swoje własne zadanie.

Jedynym powodem, dla którego mogę sobie wyobrazić, że ktoś nie chce elastyczności oferowanej przez te niesamowite dynamiczne języki, jest to, że chcą uprościć tworzenie zespołu, debugowanie i automatyczną dokumentację.

Osobiście opracowałem aplikacje w obu metodologiach i dzięki dynamicznym językom wykonuję zadania znacznie szybciej. Nie używam żadnego z tych frameworków zaprojektowanych, aby ponownie przekształcić mój dynamiczny język w język bazowy. Takie rzeczy są regresem do moich upodobań.

Lonnie Best
źródło
1

OOP oznacza dla mnie tylko wysyłanie wiadomości, lokalne przechowywanie, ochronę i ukrywanie procesów państwowych oraz ekstremalne późne wiązanie wszystkich rzeczy - Alan Kay

Mówi więc, że OO polega na tworzeniu czarnych skrzynek, które odpowiadają na wiadomości. W pewnym sensie REST jest najlepszym systemem OO, ponieważ używa czasowników (tj. Wiadomości) i zasobów (tj. Nieprzezroczystego pola zawierającego pewne dane).

Pytanie, dlaczego niektóre oparte są na klasach, a inne na prototypach, nie rozumie, że to naprawdę nie ma znaczenia, oba są jedynie implementacjami. System, który używa wyłącznie przesyłania komunikatów zamiast wywołań metod, jest tak samo OO, jak wspomniane dwa wystąpienia.

gbjbaanb
źródło