Eine Antwort auf Programmers.SE kennzeichnet einen Aufsatz von Cook ( Objekte sind keine ADTs ) als Spruch
Objekte verhalten sich eher wie eine charakteristische Funktion über die Werte eines Typs als wie eine Algebra. Objekte verwenden eher prozedurale Abstraktion als Typabstraktion
ADTs haben normalerweise eine eindeutige Implementierung in einem Programm. Wenn die eigene Sprache Module enthält, können mehrere Implementierungen eines ADT vorhanden sein, diese können jedoch normalerweise nicht zusammenarbeiten.
Es scheint mir, dass in Cooks Aufsatz zufällig ein Objekt als charakteristische Funktion für das spezifische Beispiel eines in Cooks Papier verwendeten Satzes angesehen werden kann . Ich denke nicht, dass Objekte im Allgemeinen als charakteristische Funktionen angesehen werden können.
Auch Aldritchs Artikel Die Macht der Interoperabilität: Warum Objekte unvermeidlich sind ¹ legt nahe
Die Definition von Cook identifiziert den dynamischen Versand im Wesentlichen als das wichtigste Merkmal des Objekts
mit Zustimmung dieser und mit Alan Kay , als er sagte
OOP bedeutet für mich nur Messaging, lokale Aufbewahrung und Schutz sowie das Verstecken von Staatsprozessen und die extreme Spätbindung aller Dinge.
Diese begleitenden Vorlesungsfolien zu Aldritchs Artikel legen jedoch nahe, dass Java Klassen ADTs sind, während Java-Schnittstellen Objekte sind - und tatsächlich können Schnittstellen "Objekte" zusammenarbeiten (eines der Hauptmerkmale von OOP, wie in einem der obigen Aufzählungspunkte angegeben) ).
Meine Fragen sind
Kann ich zu Recht sagen, dass charakteristische Funktionen kein Schlüsselmerkmal von Objekten sind und dass Frank Shearar sich irrt?
Sind Daten, die über Java-Schnittstellen miteinander kommunizieren, Beispiele für Objekte, obwohl sie keinen dynamischen Versand verwenden? Warum? (Mein Verständnis ist, dass der dynamische Versand flexibler ist und dass Schnittstellen ein Schritt in Richtung Messaging im Stil von Objective-C / Smalltalk / Erlang sind.)
Bezieht sich die Idee des Abhängigkeitsinversionsprinzips auf die Unterscheidung zwischen ADTs und Objekten? (Siehe die Wikipedia-Seite oder The Talking Objects: Eine Geschichte über nachrichtenorientierte Programmierung ) Obwohl ich neu im Konzept bin, verstehe ich, dass es das Hinzufügen von Schnittstellen zwischen "Ebenen" eines Programms beinhaltet (siehe Wikipedia-Seitendiagramm).
Bitte geben Sie weitere Beispiele / Erläuterungen zur Unterscheidung zwischen Objekten und ADTs an, wenn Sie dies wünschen.
¹ Dieser Artikel (veröffentlicht 2013) ist leicht zu lesen und fasst Cooks Artikel von 2009 mit Beispielen in Java zusammen. Ich empfehle dringend, es zumindest zu überfliegen, um diese Frage nicht zu beantworten, sondern nur, weil es ein gutes Papier ist.
Antworten:
Google hat eine ähnliche Frage mit einer Antwort gestellt , die ich für sehr gut halte. Ich habe es unten zitiert.
Ich möchte ein Beispiel hinzufügen.
Cook schlägt vor, dass ein Beispiel für einen abstrakten Datentyp ein Modul in C ist. In der Tat beinhalten Module in C das Ausblenden von Informationen, da es öffentliche Funktionen gibt, die über eine Header-Datei exportiert werden, und statische (private) Funktionen, die dies nicht tun. Außerdem gibt es häufig Konstruktoren (z. B. list_new ()) und Beobachter (z. B. list_getListHead ()).
Ein wesentlicher Punkt, der beispielsweise ein Listenmodul mit dem Namen LIST_MODULE_SINGLY_LINKED zu einem ADT macht, ist, dass die Funktionen des Moduls (z. B. list_getListHead ()) davon ausgehen, dass die eingegebenen Daten vom Konstruktor von LIST_MODULE_SINGLY_LINKED im Gegensatz zu einem "Äquivalent" erstellt wurden "Implementierung einer Liste (zB LIST_MODULE_DYNAMIC_ARRAY). Dies bedeutet, dass die Funktionen von LIST_MODULE_SINGLY_LINKED bei ihrer Implementierung eine bestimmte Darstellung annehmen können (z. B. eine einfach verknüpfte Liste).
LIST_MODULE_SINGLY_LINKED kann nicht mit LIST_MODULE_DYNAMIC_ARRAY zusammenarbeiten, da wir keine Daten, die beispielsweise mit dem Konstruktor von LIST_MODULE_DYNAMIC_ARRAY erstellt wurden, an den Beobachter von LIST_MODULE_SINGLY_LINKED weitergeben können, da a_
Dies ist analog zu einer Methode, mit der zwei verschiedene Gruppen aus der abstrakten Algebra nicht zusammenarbeiten können (dh Sie können das Produkt eines Elements einer Gruppe nicht mit einem Element einer anderen Gruppe kombinieren). Dies liegt daran, dass Gruppen die Closure-Eigenschaft der Gruppe annehmen (das Produkt der Elemente in einer Gruppe muss in der Gruppe sein). Wenn wir jedoch beweisen können, dass zwei verschiedene Gruppen tatsächlich Untergruppen einer anderen Gruppe G sind, können wir das Produkt von G verwenden, um zwei Elemente hinzuzufügen, eines aus jeder der beiden Gruppen.
Vergleichen der ADTs und Objekte
Cook verbindet den Unterschied zwischen ADTs und Objekten teilweise mit dem Ausdrucksproblem. Grob gesagt sind ADTs mit generischen Funktionen gekoppelt, die häufig in funktionalen Programmiersprachen implementiert sind, während Objekte mit Java- "Objekten" gekoppelt sind, auf die über Schnittstellen zugegriffen wird. Für die Zwecke dieses Textes ist eine generische Funktion eine Funktion, die einige Argumente ARGS und einen Typ TYPE (Vorbedingung) enthält. basierend auf TYPE wählt es die entsprechende Funktion aus und wertet sie mit ARGS (Post-Condition) aus. Sowohl generische Funktionen als auch Objekte implementieren Polymorphismus, aber bei generischen Funktionen weiß der Programmierer, welche Funktion von der generischen Funktion ausgeführt wird, ohne den Code der generischen Funktion zu betrachten. Bei Objekten hingegen weiß der Programmierer nicht, wie das Objekt mit den Argumenten umgehen soll, es sei denn, der Programmierer betrachtet den Code des Objekts.
Normalerweise wird das Ausdrucksproblem als "Habe ich viele Darstellungen?" "Habe ich viele Funktionen mit wenigen Darstellungen". Im ersten Fall sollte man Code nach Repräsentation organisieren (wie es am häufigsten vorkommt, insbesondere in Java). Im zweiten Fall sollte man Code nach Funktionen organisieren (dh eine einzelne generische Funktion kann mehrere Darstellungen verarbeiten).
Wenn Sie Ihren Code nach Repräsentation organisieren, sind Sie es, wenn Sie zusätzliche Funktionen hinzufügen möchten gezwungen , um die Funktionalität zu jeder Darstellung des Objekts hinzuzufügen; In diesem Sinne ist das Hinzufügen von Funktionen nicht "additiv". Wenn Sie Ihren Code durch Funktionalität organisieren, dann, wenn Sie eine zusätzliche Darstellung hinzufügen möchten - Sie sind gezwungen , die Darstellung zu jedem Objekt hinzuzufügen; in diesem Sinne Hinzufügen von Darstellungen in nicht "additiv".
Vorteil von ADTs gegenüber Objekten
Das Hinzufügen von Funktionen ist additiv
Es ist möglich, das Wissen über die Darstellung eines ADT für die Leistung zu nutzen oder zu beweisen, dass das ADT unter bestimmten Voraussetzungen eine Nachbedingung garantiert. Dies bedeutet, dass es beim Programmieren mit ADTs darum geht, die richtigen Dinge in der richtigen Reihenfolge zu tun (Vor- und Nachbedingungen zu einer "Ziel" -Nachbedingung zu verketten).
Vorteile von Objekten gegenüber ADTs
Hinzufügen von Darstellungen im Additiv
Objekte können zusammenarbeiten
Es ist möglich, Vor- / Nachbedingungen für ein Objekt anzugeben und diese wie bei ADTs miteinander zu verketten. In diesem Fall haben Objekte den Vorteil, dass (1) Darstellungen leicht geändert werden können, ohne die Schnittstelle zu ändern, und (2) Objekte zusammenarbeiten können. Dies macht jedoch den Zweck von OOP im Sinne von Smalltalk zunichte. (siehe Abschnitt "Alan Kays Version von OOP)
Dynamischer Versand ist der Schlüssel zu OOP
Es sollte jetzt offensichtlich sein, dass ein dynamischer Versand (dh eine späte Bindung) für die objektorientierte Programmierung wesentlich ist. Auf diese Weise können Prozeduren generisch definiert werden, ohne dass eine bestimmte Darstellung erforderlich ist. Konkret sein - objektorientierte Programmierung ist in Python einfach, da Methoden eines Objekts so programmiert werden können, dass keine bestimmte Darstellung angenommen wird. Aus diesem Grund benötigt Python keine Schnittstellen wie Java.
In Java sind Klassen ADTs. Eine Klasse, auf die über die von ihr implementierte Schnittstelle zugegriffen wird, ist jedoch ein Objekt.
Nachtrag: Alan Kays Version von OOP
Alan Kay bezeichnete Objekte ausdrücklich als "Familien von Algebren", und Cook schlägt vor, dass eine ADT eine Algebra ist. Daher meinte Kay wahrscheinlich, dass ein Objekt eine Familie von ADTs ist. Das heißt, ein Objekt ist die Sammlung aller Klassen, die eine Java-Schnittstelle erfüllen.
Das Bild von Objekten, die von Cook gemalt wurden, ist jedoch weitaus restriktiver als Alan Kays Vision. Er wollte, dass sich Objekte als Computer in einem Netzwerk oder als biologische Zellen verhalten. Die Idee war, das Prinzip der geringsten Verpflichtung zur Programmierung anzuwenden, damit es einfach ist, Ebenen eines ADT auf niedriger Ebene zu ändern, sobald die Ebenen auf hoher Ebene mit ihnen erstellt wurden. Vor diesem Hintergrund sind Java-Schnittstellen zu restriktiv, da ein Objekt die Bedeutung einer Nachricht nicht interpretieren kann oder sie sogar vollständig zu ignorieren.
Zusammenfassend ist die Schlüsselidee von Objekten für Kay nicht, dass sie eine Familie von Algebren sind (wie Cook betont). Die Schlüsselidee von Kay bestand vielmehr darin, ein Modell, das im Großen (Computer in einem Netzwerk) funktioniert, auf das Kleine (Objekte in einem Programm) anzuwenden.
edit: Eine weitere Klarstellung zu Kays Version von OOP: Der Zweck von Objekten besteht darin, sich einem deklarativen Ideal zu nähern. Wir sollten dem Objekt sagen, was zu tun ist - nicht sagen, wie durch Mikromanagement der Zustand ist, wie es bei prozeduraler Programmierung und ADTs üblich ist. Weitere Informationen finden Sie hier , hier , hier und hier .
edit: Ich habe hier eine sehr, sehr gute Darstellung von Alan Kays Definition von OOP gefunden .
quelle
Wenn Sie sich die ADT-Befürworter ansehen, betrachten sie eine ADT als das, was OOP eine Klasse nennen würde (interner, privater Status; eine begrenzte Anzahl von Operationen zulässig), aber es wird keine Beziehung zwischen Klassen (im Grunde keine Vererbung) berücksichtigt. Der Punkt ist stattdessen, dass das gleiche Verhalten mit verschiedenen Implementierungen erhalten werden kann. Beispielsweise kann eine Menge als Liste, Elemente in einem Array oder einer Hashtabelle oder als eine Art Baum implementiert werden.
quelle
Ich habe es immer so verstanden:
Ein ADT ist eine Schnittstelle: Es ist nur eine Sammlung von Methoden, deren Typensignaturen, möglicherweise mit Vor- und Nachbedingungen.
Eine Klasse kann ein oder mehrere ADTs implementieren , indem sie tatsächliche Implementierungen für die im ADT angegebenen Methoden angibt.
Ein Objekt ist eine Instanz einer Klasse mit einer eigenen Kopie aller nicht statischen Variablen.
Es ist möglich, dass in der Literatur die Unterscheidungen unterschiedlich sind, aber dies ist die "Standard" -Terminologie, die Sie in der Informatik hören werden.
In Java
Collection
ist beispielsweise ein ADTArrayList
eine Klasse, und Sie könnenArrayList
mit demnew
Operator ein Objekt erstellen.Die Aussage, dass ADTs normalerweise nur eine Implementierung haben, ist häufig nicht der Fall. Es ist beispielsweise möglich, dass Sie in Ihrem Programm sowohl baumbasierte als auch hashtabellenbasierte Wörterbücher verwenden möchten, je nachdem, was Sie speichern. Sie würden ein ADT gemeinsam nutzen, aber unterschiedliche Implementierungen verwenden.
quelle
Collection
Schnittstelle kein ADT ist. Es enthält eine Liste von Methoden, gibt jedoch nicht deren Semantik an. Bietet es die Semantik einer Menge? ein Multiset (Tasche)? eine geordnete Liste? Das bleibt unbestimmt. Ich bin mir also nicht sicher, ob es als ADT gilt. Das ist mein Eindruck, aber es ist durchaus möglich, dass mein Verständnis falsch ist ...