Prototypbasierte Programmierung
Prototypbasierte Programmierung ist ein Stil von Objekt orientierte Programmierung in welchem Verhalten wiederverwendet (bekannt als Nachlass) wird durch einen Prozess der Wiederverwendung bestehender durchgeführt Objekte das dient als Prototypen. Dieses Modell kann auch als bekannt als Prototypal, prototyporientiert, klassenlos, oder Instanzbasiert Programmierung.
Prototypbasierte Programmierung verwendet die verallgemeinerten Prozessobjekte, die dann kloniert und erweitert werden können. Wenn ein "Obst" -Objekt als Beispiel die Eigenschaften und Funktionalität von Obst im Allgemeinen darstellt. Ein "Banana" -Objekt würde aus dem "Obst" -Opjekt kloniert und allgemeine Eigenschaften, die spezifisch für Bananen angehängt werden, würden angehängt. Jedes einzelne "Banana" -Objekt würde aus dem generischen "Banana" -Objekt kloniert. Vergleichen mit dem Klassenbasierte Paradigma, wo eine "Frucht" Klasse würde durch eine "Banane" erweitert werden Klasse.
Der erste prototyporientierte Programmiersprache war Selbst, entwickelt von David Ungar und Randall Smith Mitte der 1980er Jahre, um Themen im objektorientierten Sprachdesign zu erforschen. Seit Ende der neunziger Jahre ist das klassenlose Paradigma immer beliebter geworden. Einige aktuelle prototyporientierte Sprachen sind JavaScript (und andere ECMaskript Implementierungen wie Jscript und Blinken's Aktionen 1.0), Lua, Cecil, NewtonScript, Io, Ioke, MUHEN, Rebol und Ahk.
Design und Implementierung
Die prototypische Vererbung in JavaScript wird durch beschrieben Douglas Crockford wie:
Sie erstellen Prototypobjekte und dann… neue Instanzen. Objekte sind in JavaScript veränderlich, sodass wir die neuen Instanzen erweitern können und ihnen neue Felder und Methoden geben. Diese können dann als Prototypen für noch neuere Objekte wirken. Wir brauchen keine Klassen, um viele ähnliche Objekte zu erstellen. Objekte erben von Objekten. Was könnte objektorientierter sein?[1]
Befürworter von prototypbasiertem Programmieren argumentieren, dass es den Programmierer ermutigt, sich auf das Verhalten einiger Beispiele zu konzentrieren und sich erst später darum kümmern, diese Objekte in archetypische Objekte zu klassifizieren, die später ähnlich wie in ähnlicher Weise verwendet werden wie Klassen.[2] Viele prototypbasierte Systeme fördern die Veränderung von Prototypen während Laufzeit, während nur sehr wenige klassenbasierte objektorientierte Systeme (z. B. das dynamische objektorientierte System, Common Lisp, Dylan, Ziel c, Perl, Python, Rubin, oder Smalltalk) Erlauben Sie, dass Klassen während der Ausführung eines Programms geändert werden.
Fast alle prototypbasierten Systeme basieren auf interpretiert und dynamisch getippt Sprachen. Systeme basierend auf statisch typisiert Sprachen sind jedoch technisch machbar. Die Omega -Sprache wurde in diskutiert Prototypbasierte Programmierung[3] ist ein Beispiel für ein solches System, obwohl laut Omegas Website sogar Omega nicht ausschließlich statisch ist, sondern der "Compiler kann sich für die statische Bindung entscheiden, wo dies möglich ist, und die Effizienz eines Programms verbessern kann".
Objektkonstruktion
In prototypbasierten Sprachen gibt es keine explizite Klassen. Objekte erben direkt von anderen Objekten durch eine Prototyp -Eigenschaft. Die Prototyp -Eigenschaft heißt Prototyp
in Selbst und JavaScript, oder Proto
in Io. Es gibt zwei Methoden zum Konstruktion neuer Objekte: aus dem Nichts ("aus nichts") Objekterstellung oder durch Klonen ein vorhandenes Objekt. Ersteres wird durch irgendeine Form von Objekt unterstützt wörtlich, Erklärungen, bei denen Objekte zur Laufzeit über spezielle Syntax wie z. B. definiert werden können {...}
und direkt an eine Variable übergeben. Während die meisten Systeme eine Vielzahl von Klonen unterstützen, aus dem Nichts Die Erstellung von Objekten ist nicht so prominent.[4]
In klassenbasierten Sprachen wird eine neue Instanz durch die einer Klasse konstruiert Konstruktorfunktion, eine spezielle Funktion, die einen Speicherblock für die Mitglieder des Objekts (Eigenschaften und Methoden) reserviert und einen Verweis auf diesen Block zurückgibt. Ein optionaler Konstruktorsatz Argumente kann an die Funktion übergeben werden und werden normalerweise in Immobilien gehalten. Die resultierende Instanz wird alle Methoden und Eigenschaften erben, die in der Klasse definiert wurden, was als eine Art Vorlage fungiert, aus der ähnlich typisierte Objekte konstruiert werden können.
Systeme, die unterstützen aus dem Nichts Die Erstellung von Objekten ermöglicht es, neue Objekte von Grund auf neu zu erstellen, ohne aus einem vorhandenen Prototyp zu klonen. Solche Systeme bieten eine spezielle Syntax für die Angabe der Eigenschaften und Verhalten neuer Objekte, ohne vorhandene Objekte zu verweisen. In vielen Prototypensprachen gibt es ein Wurzelobjekt, das oft genannt wird Objekt, der als Standardprototyp für alle anderen in der Laufzeit erstellten Objekte festgelegt wird und die üblicherweise benötigten Methoden wie a tragen tostring ()
Funktion zur Rückgabe einer Beschreibung des Objekts als Zeichenfolge. Ein nützlicher Aspekt von aus dem Nichts Die Erstellung von Objekten besteht darin, sicherzustellen, dass die Namen eines neuen Objekts (Eigenschaften und Methoden) nicht haben Namespace Konflikte mit der obersten Ebene Objekt Objekt. (In dem JavaScript Die Sprache kann dies tun, indem man einen Nullprototyp verwendet, d.h. Object.create (null)
.))
Klonen Bezieht sich auf einen Prozess, bei dem ein neues Objekt durch Kopieren des Verhaltens eines vorhandenen Objekts (seines Prototyps) konstruiert wird. Das neue Objekt trägt dann alle Eigenschaften des Originals. Ab diesem Zeitpunkt kann das neue Objekt geändert werden. In einigen Systemen hält das resultierende Kinderobjekt einen expliziten Link (über Delegation oder Ähnlichkeit) an seinen Prototyp, und Änderungen im Prototyp verursachen entsprechende Änderungen, die in seinem Klon erkennbar sind. Andere Systeme wie die Weiter-Sähnliche Programmiersprache Kevo, verbreiten Sie den Veränderung nicht vom Prototyp auf diese Weise und folgen übereinstimmend Modell, bei dem sich Änderungen in geklonten Objekten nicht automatisch über Nachkommen ausbreiten.[2]
// Beispiel eines echten prototypischen Vererbungsstils // in JavaScript. // Objekterstellung mit dem buchstäblichen // Objektnotation {}. Const Foo = { Name: "Foo", eines: 1, zwei: 2 }; // ein anderes Objekt. Const Bar = { zwei: "zwei", drei: 3 }; // Object.setPrototypeof () ist eine Methode, die in ECMascript 2015 eingeführt wurde. // Um der Einfachheit willen, lass uns so tun // dass die folgende Zeile unabhängig von der funktioniert // Motor verwendet: Objekt.setPrototypeof(Bar, Foo); // Foo ist jetzt der Prototyp der Bar. // Wenn wir versuchen, aus der Bar auf die Eigenschaften von Foo zugreifen zu können // Von nun an werden wir Erfolg haben. Bar.eines; // Auflösungen auf 1. // Die Eigenschaften des untergeordneten Objekts sind ebenfalls zugänglich. Bar.drei; // beschließt auf 3. // Eigenschaften des Schattenprototyps Eigenschaften besitzen Bar.zwei; // beschließt zu "zwei" Bar.Name; // nicht betroffen, beschließt zu "foo" Foo.Name; // beschließt zu "foo"
Für ein anderes Beispiel:
Const Foo = { eines: 1, zwei: 2 }; // bar. [[Prototyp]] = foo Const Bar = Objekt.schaffen(Foo); Bar.drei = 3; Bar.eines; // 1 Bar.zwei; // 2 Bar.drei; // 3
Delegation
In prototypbasierten Sprachen, die verwenden DelegationDie Sprachlaufzeit ist fähig zu Versand Die korrekte Methode oder das Finden des richtigen Datenstücks, indem Sie einfach einer Reihe von Delegationszeiger (vom Objekt zum Prototyp) folgen, bis eine Übereinstimmung gefunden wird. Alles, was erforderlich ist, um diese Verhaltensbeteiligung zwischen Objekten zu etablieren, ist der Delegationszeiger. Im Gegensatz zu der Beziehung zwischen Klasse und Instanz in klassenbasierten objektorientierten Sprachen erfordert die Beziehung zwischen dem Prototyp und seinen Ableger nicht, dass das untergeordnete Objekt über eine Erinnerung oder eine strukturelle Ähnlichkeit mit dem Prototyp über diese Verbindung hinaus hat. Daher kann das untergeordnete Objekt im Laufe der Zeit weiterhin modifiziert und geändert werden, ohne die Struktur seines zugehörigen Prototyps wie in klassenbasierten Systemen neu zu ordnen. Es ist auch wichtig zu beachten, dass nicht nur Daten, sondern auch Methoden hinzugefügt oder geändert werden können. Aus diesem Grund bezeichnen einige prototypbasierte Sprachen sowohl Daten als auch Methoden als "Slots" oder "Mitglieder".
Verkettung
Im übereinstimmend Prototyping - der von der Kevo -Programmiersprache implementierte Ansatz - gibt es keine sichtbaren Zeiger oder Links zum ursprünglichen Prototyp, aus dem ein Objekt kloniert wird. Das Prototyp (übergeordnete) Objekt wird eher kopiert als miteinander verbunden und es gibt keine Delegation. Infolgedessen werden Änderungen des Prototyps nicht in geklonten Objekten reflektiert.[5]
Der Hauptkonzeptunterschied in dieser Anordnung besteht darin, dass Änderungen an einem Prototypobjekt nicht automatisch an Klone ausgegeben werden. Dies kann als Vorteil oder Nachteil angesehen werden. (Kevo bietet jedoch zusätzliche Primitive für die Veröffentlichung von Änderungen für Objekte, die auf ihrer Ähnlichkeit basieren-so genannte Familienähnlichkeit oder Klonfamilie Mechanismus[5] -und nicht durch taxonomische Herkunft, wie es im Delegationsmodell typisch ist.) Manchmal wird auch behauptet, dass delegationsbasierter Prototyping einen zusätzlichen Nachteil aufweist, da Änderungen an einem untergeordneten Objekt den späteren Betrieb des Elternteils beeinflussen können. Dieses Problem ist jedoch nicht dem delegationsbasierten Modell innewohnt und existiert nicht in delegationsbasierten Sprachen wie JavaScript, die sicherstellen Wert beschattet den Wert des Elternteils, anstatt den Wert des Elternteils zu ändern).
In simplen Implementierungen wird eingehungerisches Prototyping eine schnellere Suchausschau von Mitgliedern aufweisen als auf Delegationsbasis-Prototyping (da es nicht erforderlich ist, der Kette der übergeordneten Objekte zu folgen), sondern umgekehrt mehr Speicher (da alle Slots kopiert werden, anstatt es gibt eine einzelne Slot, der auf das übergeordnete Objekt zeigt). Ausgefugtere Implementierungen können dieses Problem jedoch vermeiden, obwohl Kompromisse zwischen Geschwindigkeit und Speicher erforderlich sind. Zum Beispiel können Systeme mit verkettender Prototyping a verwenden Kopieren auf dem Schreiben Implementierung, um die Datenaustausch hinter den Kulissen zu ermöglichen-und auf einen solchen Ansatz folgt tatsächlich Kevo.[6] Umgekehrt können Systeme mit delegationsbasiertem Prototyping verwendet werden zwischengespeichert Um die Daten zu beschleunigen.
Kritik
Befürworter klassenbasierter Objektmodelle, die prototypbasierte Systeme kritisieren Datentyp). Normalerweise umfassen solche Bedenken: Richtigkeit, Sicherheit, Vorhersagbarkeit, Effizienz und Programmierer Unbekanntheit.
Bei den ersten drei Punkten werden Klassen häufig als analog zu Typen (in den am meisten statisch typisierten objektorientierten Sprachen, die sie dieser Rolle spielen) In gewisser Weise.
In Bezug auf die Effizienz vereinfacht das Erklärungsklassen viele Compiler Optimierungen, die es ermöglichen, eine effiziente Methode und eine Instanzvariable zu entwickeln. Für die Selbst Sprache, viel Entwicklungszeit wurde für die Entwicklung, Kompilierung und Interpretation von Techniken zur Verbesserung der Leistung von prototypbasierten Systemen gegenüber klassenbasierten Systemen aufgewendet.
Eine häufige Kritik gegen prototypbasierte Sprachen ist, dass die Gemeinschaft von Softwareentwickler ist mit ihnen nicht vertraut, trotz der Popularität und der Marktpermeation von JavaScript. Dieses Wissensniveau an prototypbasierten Systemen scheint mit der Verbreitung von JavaScript -Frameworks und die komplexe Verwendung von JavaScript als die Netz reift.[7] ECMascript 6 führte Klassen als vor syntethischer Zucker Über JavaScripts vorhandenes prototypbasiertes Vererbung bietet eine alternative Möglichkeit, Objekte zu erstellen und mit der Vererbung umzugehen.[8]
Sprachen, die prototypbasierte Programmierung unterstützen
- Actor-basierte gleichzeitige Sprache (ABCL): ABCL/1, Abcl/r, ABCL/R2, ABCL/C+
- Agora
- Autohotkey
- Cecil und Diesel von Craig Chambers
- Coldc
- COLA
- Common Lisp
- Cyan
- ECMaskript
- Aktionen 1.0, verwendet von Adobe Flash und Adobe Flex
- E4X
- JavaScript
- Jscript
- Typoskript
- Io
- Ioke
- Jsonnet
- Logtalk
- LPC
- Lua
- M2000
- Ahorn
- MUHEN
- Neko
- NewtonScript
- Nim
- Nix
- Objekt Lisp
- Obliq
- Omega
- OpenLaszlo
- Perl, mit der Klasse :: Prototyped Modul
- Python mit prototype.py.
- Rmit dem Protopaket
- Rebol
- Rot (Programmiersprache)
- Ruby (Programmiersprache)
- Selbst
- Seph
- Schiefer (Programmiersprache)
- SmartFrog
- Schnapp!
- ETOYS
- Nichts
- Tcl mit Snit -Erweiterung
- Umajin[9]
Siehe auch
Verweise
- ^ Crockford, Douglas. "Prototypaler Vererbung in JavaScript". Abgerufen 22. Juni 2021.
- ^ a b Taivalsaari, Antero (1996). "Abschnitt 1.1". Klassen vs. Prototypen: Einige philosophische und historische Beobachtungen. S. 44–50. Citeseerx 10.1.1.56.4713.
- ^ Blassek, Günther. "Abschnitt 2.8". Omega: statisch typisierte Prototypen. p. 177.
- ^ Dony, Chistophe; Malenfan, Jacques; Bardou, Daniel. "Abschnitt 1.2" (PDF). Klassifizierung von prototypbasierten Programmiersprachen klassifizieren. p. 17.
- ^ a b Antero Taivalsaar (2009). "Vereinfachung des JavaScripts mit einer verkettungsbasierten Prototyp-Vererbung" (PDF). Tampere University of Technology. Archiviert von das Original auf 2009. Abgerufen 2015-03-11.
Kevo implementierte ein reines, verkettungsbasiertes Objektmodell, bei dem durch Kopieren neue Objekte erstellt wurden, und die Namespaces aller Objekte waren immer vollständig in sich geschlossen. … Außerdem hatte Kevo eine interne Klonfamilie Der Mechanismus, der es ermöglichte, die „Genealogie“ von Änderungen zwischen Gruppen von Objekten zu verfolgen, so dass Änderungen an einzelnen Objekten bei Bedarf an andere Objekte verbreitet werden können.
- ^ Taivalsaari, Antero (1992). "Kevo, eine prototypbasierte objektorientierte Programmiersprache, die auf Verkettung und Moduloperationen basiert". Technischer Bericht LACIR 92-02. Universität von Victoria.
- ^ "Prototypal objektorientierte Programmierung mit JavaScript". Eine Liste auseinander. 2016-04-26. Abgerufen 2018-10-21.
- ^ "Klassen". JavaScript -Referenz. Mozilla Developer Network. Abgerufen 9. Februar 2016.
- ^ Proprietäre Skriptsprache. http://www.davidbrebner.com/?p=4 hat einige grundlegende Verwendung.
Weitere Lektüre
- Abadi, Martin; Luca Cardelli (1996). Eine Theorie der Objekte. Springer-Verlag. ISBN 978-1-4612-6445-3.
- Klassenkrieg: Klassen vs. Prototypen, von Brian Foote.
- Noble, James; Taivalsaari, Antero; Moore, Ivan, Hrsg. (1999). Prototypbasierte Programmierung: Konzepte, Sprachen und Anwendungen. Springer-Verlag. ISBN 981-4021-25-3.
- Verwendung prototypischer Objekte zur Implementierung eines gemeinsam genutzten Verhaltens in objektorientierten Systemen, von Henry Lieberman, 1986.