Im ersten Semester wurden wir mit OOP-Konzepten wie Kapselung, Verstecken von Daten, Modularität, Vererbung usw. über Java und UML vertraut gemacht. (Java ist meine erste Programmiersprache)
Keines davon sind OOP-Konzepte. Sie existieren alle außerhalb von OO, unabhängig von OO und viele wurden sogar vor OO erfunden.
Wenn Sie also der Meinung sind, dass OO genau das ist, dann ist Ihre Schlussfolgerung richtig: Sie können all dies in prozeduralen Sprachen tun , weil sie nichts mit OO zu tun haben .
Eine der bahnbrechenden Arbeiten zum Thema Modularität befasst sich beispielsweise mit den Kriterien für die Zerlegung von Systemen in Module . Es gibt dort keine Erwähnung von OO. (Es wurde 1972 geschrieben, bis dahin war OO immer noch eine dunkle Nische, obwohl es bereits mehr als ein Jahrzehnt alt war.)
Während Datenabstraktion in OO wichtig ist, ist sie eher eine Folge der Hauptfunktion von OO (Messaging) als eine definierende Funktion. Es ist auch sehr wichtig, sich daran zu erinnern, dass es verschiedene Arten der Datenabstraktion gibt. Die beiden am häufigsten verwendeten Arten der Datenabstraktion (wenn wir "überhaupt keine Abstraktion" ignorieren, die wahrscheinlich immer noch häufiger verwendet wird als die beiden anderen zusammen) sind abstrakte Datentypen und Objekte . Wenn Sie also "Information Hiding", "Encapsulation" und "Data Abstraction" sagen, haben Sie nichts über OO gesagt, da OO nur eine Form der Datenabstraktion ist und die beiden sich in der Tat grundlegend unterscheiden:
- Bei abstrakten Datentypen ist der Mechanismus für die Abstraktion das Typensystem . Es ist das Typsystem, das die Implementierung verbirgt. (Das Typensystem muss nicht unbedingt statisch sein.) Bei Objects ist die Implementierung hinter einer prozeduralen Schnittstelle verborgen , für die keine Typen erforderlich sind. (Zum Beispiel kann es mit Closures implementiert werden, wie es in ECMAScript gemacht wird.)
- Bei abstrakten Datentypen sind Instanzen verschiedener ADTs voneinander gekapselt, Instanzen desselben ADT können jedoch die Darstellung und die private Implementierung des jeweils anderen prüfen und auf diese zugreifen. Objekte sind immer von allem gekapselt . Nur das Objekt selbst kann seine eigene Darstellung überprüfen und auf seine eigene private Implementierung zugreifen. Kein anderes Objekt , nicht einmal andere Objekte desselben Typs, andere Instanzen derselben Klasse, andere Objekte mit demselben Prototyp, Klone des Objekts oder was auch immer können das tun. Keine .
Dies bedeutet im Übrigen, dass Klassen in Java nicht objektorientiert sind. Zwei Instanzen derselben Klasse können auf die Repräsentation und die private Implementierung des jeweils anderen zugreifen. Daher sind Instanzen von Klassen keine Objekte, sondern ADT-Instanzen. Java interface
s, aber sie bieten objektorientierte Datenabstraktion. Mit anderen Worten: Nur Instanzen von Interfaces sind Objekte in Java, Instanzen von Klassen nicht.
Grundsätzlich können Sie für Typen nur Schnittstellen verwenden. Dies bedeutet, dass Parametertypen von Methoden und Konstruktoren, Rückgabetypen von Methoden, Typen von Instanzfeldern, statischen Feldern und lokalen Feldern, das Argument für einen instanceof
Operator oder einen Umwandlungsoperator und die Typargumente für einen generischen Typkonstruktor immer Schnittstellen sein müssen. Eine Klasse darf nur direkt nach dem new
Operator verwendet werden, nirgendwo anders.
Zum Beispiel können wir das Programm aus Gründen der Modularität einfach in viele kleine Programme aufteilen, die genau definierte Aufgaben ausführen, deren Code in separaten Dateien enthalten ist. Diese Programme würden durch ihre wohldefinierte Eingabe und Ausgabe miteinander interagieren. Die Dateien können geschützt (verschlüsselt?) Sein, um eine Kapselung zu erreichen. Zur Wiederverwendung von Code können wir diese Dateien nur aufrufen, wenn sie in neuen Programmen benötigt werden. Erfasst das nicht alles, was OOP ist, oder vermisse ich etwas sehr Offensichtliches?
Was Sie beschreiben, ist OO.
Das ist in der Tat eine gute Möglichkeit, über OO nachzudenken. Genau das haben sich die ursprünglichen Erfinder von OO vorgenommen. (Alan Kay ging noch einen Schritt weiter: Er stellte sich viele kleine Computer vor, die sich gegenseitig Nachrichten über das Netzwerk senden.) Was Sie als "Programm" bezeichnen, wird normalerweise als "Objekt" bezeichnet, und statt "Aufrufen" sagen wir normalerweise "Nachricht senden" ".
Bei der Objektorientierung dreht sich alles um Messaging (auch bekannt als dynamischer Versand ). Der Begriff "Objektorientiert" wurde von Dr. Alan Kay, dem Hauptdesigner von Smalltalk, geprägt und definiert ihn folgendermaßen :
OOP bedeutet für mich nur Nachrichtenübermittlung, lokale Aufbewahrung und Schutz sowie das Verstecken von staatlichen Prozessen und extrem spätes Binden aller Dinge.
Lassen Sie uns das zusammenfassen:
- Messaging ("Versand virtueller Methoden", wenn Sie nicht mit Smalltalk vertraut sind)
- Staats-Prozess sollte sein
- vor Ort aufbewahrt
- geschützt
- versteckt
- extreme Spätbindung aller Dinge
In Bezug auf die Implementierung ist Messaging ein spät gebundener Prozeduraufruf. Wenn Prozeduraufrufe spät gebunden sind, können Sie zur Entwurfszeit nicht wissen, was Sie aufrufen werden, sodass Sie keine Annahmen über die konkrete Darstellung des Status treffen können. Eigentlich geht es also um Messaging. Late-Binding ist eine Implementierung von Messaging, und Encapsulation ist eine Folge davon.
Später stellte er klar, dass " die große Idee" Messaging "ist, und bedauert, sie" objektorientiert "statt" nachrichtenorientiert "genannt zu haben, weil der Begriff" objektorientiert "den Fokus auf das Unwichtige (Objekte) legt ) und lenkt von dem ab, was wirklich wichtig ist (Messaging):
Nur eine sanfte Erinnerung daran, dass ich bei der letzten OOPSLA einige Anstrengungen unternommen habe, um alle daran zu erinnern, dass Smalltalk nicht nur NICHT seine Syntax oder die Klassenbibliothek ist, sondern nicht einmal Klassen. Es tut mir leid, dass ich den Begriff "Objekte" für dieses Thema vor langer Zeit geprägt habe, weil es viele Leute dazu bringt, sich auf die geringere Idee zu konzentrieren.
Die große Idee ist "Messaging" - darum geht es bei Smalltalk / Squeak (und es ist etwas, das in unserer Xerox-PARC-Phase nie ganz abgeschlossen wurde). Die Japaner haben ein kleines Wort - ma - für "das, was dazwischen liegt" - vielleicht ist das nächste englische Äquivalent "interstitial". Der Schlüssel zur Entwicklung großartiger und erweiterbarer Systeme liegt vielmehr in der Gestaltung der Kommunikation der Module als in der Festlegung der internen Eigenschaften und Verhaltensweisen. Denken Sie an das Internet - um zu leben, muss es (a) viele verschiedene Arten von Ideen und Realisierungen zulassen, die über einen bestimmten Standard hinausgehen, und (b) ein unterschiedliches Maß an sicherer Interoperabilität zwischen diesen Ideen ermöglichen.
(Natürlich konzentrieren sich die meisten Menschen heute nicht mehr auf Objekte, sondern auf Klassen, was noch falscher ist.)
Messaging ist für OO sowohl als Metapher als auch als Mechanismus von grundlegender Bedeutung .
Wenn Sie jemandem eine Nachricht senden, wissen Sie nicht, was er damit macht. Das einzige, was Sie beobachten können, ist ihre Antwort. Sie wissen nicht, ob sie die Nachricht selbst verarbeitet haben (dh ob das Objekt eine Methode hat), ob sie die Nachricht an eine andere Person weitergeleitet haben (Delegation / Proxying) oder ob sie sie überhaupt verstanden haben. Darum geht es bei der Verkapselung, darum geht es bei OO. Sie können einen Proxy nicht einmal von der Realität unterscheiden, solange er so reagiert, wie Sie es erwarten.
Ein "moderner" Begriff für "Messaging" ist "dynamischer Methodenversand" oder "virtueller Methodenaufruf", der jedoch die Metapher verliert und sich auf den Mechanismus konzentriert.
Es gibt also zwei Möglichkeiten, die Definition von Alan Kay zu betrachten: Wenn Sie sich die Definition einzeln ansehen, stellen Sie möglicherweise fest, dass Messaging im Grunde genommen ein späteingebundener Prozeduraufruf ist und eine späte Bindung eine Verkapselung impliziert und # 2 sind eigentlich überflüssig, und OO dreht sich alles um spätes Binden.
Später stellte er jedoch klar, dass das Wichtigste das Versenden von Nachrichten ist, sodass wir es aus einem anderen Blickwinkel betrachten können: Nachrichtenversenden ist verspätet. Wenn Messaging das einzig mögliche wäre, dann wäre # 3 trivial wahr: Wenn es nur eine Sache gibt und diese Sache verspätet gebunden ist, dann sind alle Dinge verspätet gebunden. Die Verkapselung ergibt sich wiederum aus dem Messaging.
Ähnliche Punkte finden sich auch in On Understanding Data Abstraction, überarbeitet von William R. Cook, und in seinem Vorschlag für vereinfachte, moderne Definitionen von "Objekt" und "objektorientiert" :
Der dynamische Versand von Vorgängen ist das wesentliche Merkmal von Objekten. Dies bedeutet, dass die aufzurufende Operation eine dynamische Eigenschaft des Objekts selbst ist. Operationen können nicht statisch identifiziert werden, und es gibt im Allgemeinen keine Möglichkeit, genau zu wissen, welche Operation als Antwort auf eine bestimmte Anforderung ausgeführt wird, es sei denn, sie wird ausgeführt. Dies ist genau das gleiche wie bei erstklassigen Funktionen, die immer dynamisch abgesetzt werden.
In Smalltalk-72 gab es nicht einmal Gegenstände! Es gab nur Nachrichtenströme, die analysiert, umgeschrieben und umgeleitet wurden. Zuerst kamen Methoden (Standardmethoden zum Parsen und Umleiten der Nachrichtenströme), später kamen Objekte (Gruppierungen von Methoden, die einen privaten Status gemeinsam haben). Die Vererbung erfolgte viel später, und Klassen wurden nur eingeführt, um die Vererbung zu unterstützen. Wäre Kays Forschungsgruppe bereits über Prototypen informiert gewesen, hätte sie wahrscheinlich niemals Klassen eingeführt.
Benjamin Pierce in Types and Programming Languages argumentiert, dass das bestimmende Merkmal der Objektorientierung die offene Rekursion ist .
Also: Laut Alan Kay dreht sich bei OO alles um Messaging. Laut William Cook dreht sich bei OO alles um den Versand dynamischer Methoden (was eigentlich dasselbe ist). Laut Benjamin Pierce dreht sich bei OO alles um Open Recursion, was im Grunde bedeutet, dass Selbstreferenzen dynamisch aufgelöst werden (oder zumindest so), oder mit anderen Worten, Messaging.
Wie Sie sehen, hat die Person, die den Begriff "OO" geprägt hat, eine eher metaphysische Sicht auf Objekte, Cook eine eher pragmatische Sicht und Pierce eine sehr rigorose mathematische Sicht. Aber das Wichtige ist: Der Philosoph, der Pragmatiker und der Theoretiker sind sich einig! Messaging ist die eine Säule von OO. Zeitraum.
Beachten Sie, dass hier keine Vererbung erwähnt wird! Vererbung ist für OO nicht wesentlich. Im Allgemeinen haben die meisten OO-Sprachen eine Möglichkeit zur Wiederverwendung der Implementierung, dies muss jedoch nicht unbedingt eine Vererbung sein. Dies kann beispielsweise auch eine Form der Delegation sein. Tatsächlich wird im Vertrag von Orlando die Delegation als Alternative zur Vererbung erörtert und wie unterschiedliche Formen der Delegation und Vererbung zu unterschiedlichen Entwurfspunkten im Entwurfsraum objektorientierter Sprachen führen. (Beachten Sie, dass die Leute auch in Sprachen, die Vererbung unterstützen, wie Java, tatsächlich lernen, dies zu vermeiden, was wiederum darauf hinweist, dass dies für OO nicht erforderlich ist.)