Hinweis : Diese Frage ist ein bearbeiteter Auszug aus einem Blogeintrag, den ich vor einigen Monaten verfasst habe. Nachdem ich in einem Kommentar zu Programmers.SE einen Link zum Blog eingefügt hatte, bat mich jemand, eine Frage hier zu stellen, damit sie beantwortet werden konnte. Dieses Posting ist mein beliebtestes, da die Leute scheinbar "Ich bekomme keine objektorientierte Programmierung" in Google eingeben . Fühlen Sie sich frei, hier oder in einem Kommentar bei Wordpress zu antworten.
Was ist objektorientierte Programmierung? Niemand hat mir eine zufriedenstellende Antwort gegeben. Ich habe das Gefühl, Sie werden keine gute Definition von jemandem bekommen, der herumläuft und "Objekt" und "objektorientiert" mit der Nase in der Luft sagt. Sie erhalten auch keine gute Definition von jemandem, der nichts anderes als objektorientierte Programmierung durchgeführt hat. Niemand, der sowohl die prozedurale als auch die objektorientierte Programmierung versteht, hat mir jemals eine einheitliche Vorstellung davon gegeben, was ein objektorientiertes Programm tatsächlich tut.
Kann mir bitte jemand eine Vorstellung von den Vorteilen der objektorientierten Programmierung geben?
quelle
Antworten:
Stellen Sie sich Software als Maschine oder Fließband vor, das im Computer vorhanden ist. Einige Rohstoffe und Komponenten werden der Maschine zugeführt, und es werden eine Reihe von Verfahren befolgt, um sie zu einem Endprodukt zu verarbeiten. Die Verfahren sind so eingerichtet, dass ein bestimmter Vorgang an einem Rohmaterial oder einer Komponente mit einem bestimmten Parametersatz (z. B. Zeit, Temperatur, Entfernung usw.) in einer bestimmten Reihenfolge durchgeführt wird. Wenn die Details der auszuführenden Operation nicht korrekt waren oder die Sensoren der Maschine nicht korrekt kalibriert waren oder wenn ein Rohmaterial oder eine Komponente nicht den erwarteten Qualitätsstandards entsprach, konnte dies das Ergebnis der Operation verändern und das Produkt würde nicht ausfallen wie erwartet.
Eine solche Maschine ist in ihrem Betrieb sehr steif und in ihren Eingaben akzeptabel. Maschinen stellen weder die Intelligenz der Konstrukteure noch ihre aktuelle Betriebsumgebung in Frage. Es wird weiterhin Verfahren folgen, solange es gerichtet ist. Selbst wenn sich eine Änderung der Rohstoffe oder Komponenten dramatisch auf die späteren Arbeitsabläufe auswirken würde, würde die Maschine dennoch ihre Arbeitsabläufe ausführen. Der Prozess müsste überprüft werden, um festzustellen, welche Änderungen an den Verfahren erforderlich sind, um das gewünschte Ergebnis zu kompensieren und zu erzielen. Eine Änderung des Designs oder der Konfiguration des Produkts kann auch eine erhebliche Änderung der durchgeführten Vorgänge oder ihrer Reihenfolge erforderlich machen. Obwohl die für die Produktion Verantwortlichen schnell die Wichtigkeit der größtmöglichen Isolierung von Vorgängen erkannten, um unerwünschte Auswirkungen zwischen ihnen zu verringern, Es werden viele Annahmen darüber getroffen, in welchem Zustand sich die Komponenten befinden, während sie verarbeitet werden. Annahmen, die möglicherweise erst erkannt werden, wenn sich das Endprodukt in einer anderen Betriebsumgebung in den Händen des Benutzers befindet.
So ist die prozedurale Programmierung.
Die Objektorientierung bietet eine Möglichkeit, die Annahmen über den Zustand von Komponenten zu entfernen. Auf diese Weise werden die an dieser Komponente auszuführenden Vorgänge und deren Integration in das Endprodukt beschrieben. Mit anderen Worten, OOP ist so, als würde man die Prozessdetails für den Umgang mit einer bestimmten Komponente übernehmen und sie einer kleineren Maschine übergeben. Die größere Maschine, die für den Prozess verantwortlich ist, teilt der komponentenspezifischen Maschine mit, welche Operation sie erwartet, überlässt jedoch die Details für die Schritte der komponentenspezifischen Maschine.
Zu den Vorteilen der Objektorientierung gegenüber nicht-objektorientierter Software:
quelle
Aus Ihrem Blog geht hervor, dass Sie sowohl mit der imperativen als auch mit der funktionalen Programmierung vertraut sind und mit den grundlegenden Konzepten der objektorientierten Programmierung vertraut sind, aber Sie hatten noch nie einen richtigen "Klick" macht es nützlich. Ich werde versuchen, in Bezug auf dieses Wissen zu erklären, und hoffe, dass es für Sie hilfreich ist.
Im Kern ist OOP eine Möglichkeit, das zwingende Paradigma zu verwenden, um hohe Komplexitätsgrade besser zu verwalten, indem "intelligente" Datenstrukturen erstellt werden, die die Problemdomäne modellieren. In einem (standardmäßigen prozeduralen, nicht objektorientierten) Programm haben Sie zwei grundlegende Dinge: Variablen und Code, der weiß, was er damit machen soll. Der Code nimmt Eingaben vom Benutzer und verschiedenen anderen Quellen entgegen, speichert sie in Variablen, verarbeitet sie und erzeugt Ausgabedaten, die an den Benutzer oder verschiedene andere Stellen gehen.
Objektorientierte Programmierung ist eine Möglichkeit, Ihr Programm zu vereinfachen, indem dieses Grundmuster verwendet und in kleinerem Maßstab wiederholt wird. So wie ein Programm eine große Sammlung von Daten mit Code ist, die wissen, was damit zu tun ist, ist jedes Objekt eine kleine Datenmenge, die an Code gebunden ist und weiß, was damit zu tun ist.
Indem Sie die Problemdomäne in kleinere Teile aufteilen und sicherstellen, dass so viele Daten wie möglich direkt an Code gebunden sind, der weiß, was damit zu tun ist, können Sie den gesamten Prozess und auch die untergeordneten Aspekte besser beurteilen. Fragen, die den Prozess ausmachen.
Durch Gruppieren von Daten in Objektklassen können Sie den Code für diese Daten zentralisieren, sodass relevanter Code leichter gefunden und behoben werden kann. Indem Sie die Daten hinter den Zugriffsspezifizierern einkapseln und nur über Methoden (oder Eigenschaften, sofern Ihre Sprache diese unterstützt) darauf zugreifen, verringern Sie das Risiko von Datenbeschädigungen oder Verstößen gegen Invarianten erheblich.
Durch die Verwendung von Vererbung und Polymorphismus können Sie bereits vorhandene Klassen wiederverwenden und an Ihre spezifischen Anforderungen anpassen, ohne die Originale ändern oder alles von Grund auf neu schreiben zu müssen. (Was Sie niemals tun sollten , wenn Sie es vermeiden können.) Achten Sie nur darauf, dass Sie Ihr Basisobjekt verstehen, sonst könnten Sie Killerkängurus bekommen .
Für mich sind dies die Grundprinzipien der objektorientierten Programmierung: Komplexitätsmanagement, Codezentralisierung und verbesserte Problemdomänenmodellierung durch die Erstellung von Objektklassen, Vererbung und Polymorphismus sowie erhöhte Sicherheit ohne Einbußen bei Leistung oder Kontrolle durch die Verwendung von Kapselung und Eigenschaften. Ich hoffe, das hilft Ihnen zu verstehen, warum so viele Programmierer es nützlich finden.
EDIT: Als Antwort auf Joel Frage in den Kommentaren,
Ein kleiner Haftungsausschluss hier. Mein Modell eines "objektorientierten Programms" ist im Grunde das Delphi-Modell, das dem C # /. NET-Modell sehr ähnlich ist, da es von ehemaligen Delphi-Teammitgliedern erstellt wurde. Was ich hier sage, trifft möglicherweise nicht oder nicht so häufig auf andere OO-Sprachen zu.
Ein objektorientiertes Programm ist eines, bei dem die gesamte Logik um Objekte herum strukturiert ist. Natürlich muss dies irgendwo gebootet werden. Ein typisches Delphi-Programm enthält Initialisierungscode, mit dem ein Singleton-Objekt namens erstellt wird
Application
. Zu Beginn des Programms wird für jedes Formular, das Sie von Anfang an in den Speicher laden möchtenApplication.Initialize
, ein AufrufApplication.CreateForm
von ausgeführt. AnschließendApplication.Run,
wird das Hauptformular auf dem Bildschirm angezeigt und die Eingabe- / Ereignisschleife gestartet, die den Kern eines jeden Formulars bildet Interaktive Computerprogramme.Die Anwendung und Ihre Formulare suchen nach eingehenden Ereignissen vom Betriebssystem und übersetzen sie in Methodenaufrufe für Ihr Objekt. Eine Sache, die sehr häufig vorkommt, ist die Verwendung von Ereignishandlern oder "Delegaten" in .NET-Sprache. Ein Objekt hat eine Methode, die besagt, "mache X und Y, prüfe aber auch, ob dieser spezielle Event-Handler zugewiesen ist, und rufe ihn auf, wenn dies der Fall ist." Ein Ereignishandler ist ein Methodenzeiger - ein sehr einfacher Abschluss, der einen Verweis auf die Methode und einen Verweis auf die Objektinstanz enthält -, mit dem das Verhalten von Objekten erweitert wird. Wenn ich zum Beispiel ein Schaltflächenobjekt in meinem Formular habe, passe ich sein Verhalten an, indem ich einen OnClick-Ereignishandler anhänge, der bewirkt, dass ein anderes Objekt eine Methode ausführt, wenn auf die Schaltfläche geklickt wird.
In einem objektorientierten Programm werden die meisten Aufgaben erledigt, indem Objekte mit bestimmten Verantwortlichkeiten definiert und miteinander verknüpft werden, entweder durch Methodenzeiger oder durch ein Objekt, das direkt eine in der öffentlichen Schnittstelle eines anderen Objekts definierte Methode aufruft. (Und jetzt kehren wir zur Kapselung zurück.) Dies ist eine Idee, von der ich kein Konzept hatte, bevor ich OOP-Kurse am College belegte.
quelle
Ich denke, OOP ist im Grunde nur ein Name für etwas, zu dem Sie auf dem Weg versucht waren, so wie ich.
Vor langer Zeit, als ich ein Baby-Programmierer war, gab es sogar in Fortran so etwas wie einen Zeiger auf ein Unterprogramm. Es ist sehr nützlich, einen Zeiger auf ein Unterprogramm als Argument für ein anderes Unterprogramm übergeben zu können.
Dann wäre das nächste, was wirklich nützlich wäre, einen Zeiger auf eine Unterroutine in einem Datensatz einer Datenstruktur zu speichern. Auf diese Weise könnte man sagen, der Datensatz "weiß", wie Operationen an sich selbst ausgeführt werden.
Ich bin mir nicht sicher, ob sie das jemals in Fortran eingebaut haben, aber es ist einfach in C und seinen Nachkommen zu tun.
Darunter ist es also eine einfache und nützliche Idee, die Sie vielleicht in Versuchung gebracht haben, selbst zu tun, und die in neueren Sprachen einfacher zu tun ist, selbst wenn einige Leute sie in einen riesigen Zug voller gruseliger Schlagworte verwandelt haben.
quelle
Es gibt verschiedene Arten von OO-Systemen, und es ist schwierig, eine Definition zu finden, auf die sich alle einigen werden. Anstatt zu zeigen, wie Javas OO dem Common Lisp Object System ähnelt, beginne ich Schritt für Schritt mit etwas Konventionellerem.
Angenommen, Sie haben viele Objekte als verteilte Daten. Punkte können beispielsweise Elemente in einem X-, Y- und Z-Array sein. Um einen Punkt selbst zu betrachten, ist es sinnvoll, alle Daten zu einem C zusammenzufassen
struct
.Jetzt haben wir für jedes Datenobjekt alle Daten zusammen. In einem prozeduralen Programm ist der Code jedoch verstreut. Angenommen, wir haben es mit geometrischen Formen zu tun. Es gibt eine große Funktion zum Zeichnen von Formen, und es muss über alle Formen Bescheid wissen. Es gibt eine große Funktion zum Finden des Bereichs und eine für den Umkreis. Der Code für einen Kreis ist über mehrere Funktionen verteilt, und um einen anderen Formtyp hinzuzufügen, müssen wir wissen, welche Funktionen geändert werden müssen. In einem objektorientierten System sammeln wir die Funktionen in der gleichen Art von Dingen (
class
) wie die Daten. Wenn wir uns also den gesamten Kreiscode ansehen wollen, steht er in derCircle
Definition, und wenn wir einen hinzufügen wollen,Quartercircle
schreiben wir einfach seine Klasse und wir haben den Code.Ein Nebeneffekt davon ist, dass wir Klasseninvarianten beibehalten können, Dinge, die für jedes Mitglied der Klasse zutreffen. Indem der Code außerhalb der Klasse daran gehindert wird, direkt mit Klassendatenmitgliedern in Berührung zu kommen, haben wir den gesamten Code, der Klassendaten an einer Stelle ändern kann, und wir können bestätigen, dass er nichts Verrücktes bewirkt (wie ein Dreieck mit einem Bein) länger als die beiden anderen zusammen). Dies bedeutet, dass wir uns bei jedem Mitglied der Klasse auf einige Eigenschaften verlassen können und nicht jedes Mal prüfen müssen, ob ein Objekt vernünftig ist, wenn wir es verwenden.
Der Hauptvorteil liegt in der Vererbung und dem Polymorphismus. Indem wir all diese verschiedenen Formen als Unterklassen einer Klasse definieren, die aufgerufen wird
Shape
, können wir unseren CodeShape
s manipulieren lassen , und es ist die Aufgabe der Form-Unterobjekte, alles zu tun, was durch die Manipulationen gefordert wird. Dies bedeutet, dass wir den alten getesteten Code nicht berühren müssen, wenn wir neue Formen hinzufügen oder das Verhalten älterer Formen verfeinern. Wir haben automatisch alten Code, der neuen Code direkt nutzen kann. Anstatt den Steuercode auf die verschiedenen möglichen Formen aufmerksam zu machen und Funktionen zu verwalten, die die verschiedenen möglichen Formen kennen, werden lediglich Formen und ihre Eigenschaften behandelt, währendShape
Unterklassen beibehalten werden . Dies vereinfacht den Steuercode.Wir haben hier mehrere Vorteile. Da wir Klasseninvarianten haben, können wir über größere Datenobjekte genauso urteilen wie über eingebaute Typen, was bedeutet, dass wir komplexe Konzepte oft in einfachere Konzepte aufteilen können. Da der Kreiscode weitgehend in enthalten ist
Circle
, haben wir die Lokalität erhöht. Da es keine Konzepte eines Kreises gibt, die über mehrere verschiedene Funktionen an verschiedenen Orten verstreut sind, erhalten wir weniger Kopplung zwischen Routinen und müssen uns nicht darum kümmern, sie synchron zu halten. Da es sich bei Klassen im Grunde genommen um Typen handelt, können wir das vorhandene Typensystem nutzen, um eine inkompatible Verwendung unserer Klassen zu ermitteln.quelle
OO hat viele verschiedene Definitionen, ja. Ich bin sicher, dass Sie viele davon selbst finden können. Ich persönlich mag Rees Re: OO , um ihnen einen Sinn zu geben. Ich vermute, Sie haben das schon gelesen, seit Sie Paul Graham zitiert haben. (Ich empfehle es jedem, der sich für OO interessiert.) Ich werde hier mehr oder weniger die Java-Definition übernehmen {1,2,3,7,8,9}.
Die Frage nach dem Nutzen von OO, insbesondere die Art und Weise, wie ich sie betrachte, verdient eine viel umfassendere Antwort mit ein paar tausend Codezeilen (teilweise, um nicht nur ein Bündel von Behauptungen zu sein). Hier ist jedoch eine Zusammenfassung dieses hypothetischen Dokuments.
Ich denke nicht, dass OO in kleinem Maßstab furchtbar nützlich ist, sagen wir ein paar hundert Zeilen. Insbesondere OO-Sprachen ohne gute funktionale Einflüsse machen es oft sehr schmerzhaft, einfache Dinge mit jeder Art von Sammlung oder allem, was viele Datentypen benötigt, zu erledigen. Hier kommen die meisten Designmuster ins Spiel; Sie sind Pflasterer für die geringe Leistungsfähigkeit der zugrunde liegenden Sprache .
Bei ungefähr tausend Zeilen wird es schwieriger, alle Vorgänge und Datenstrukturen und deren Beziehung zu verfolgen. An dieser Stelle ist es hilfreich, Datenstrukturen und -vorgänge explizit zu organisieren, Modulgrenzen zu zeichnen und Verantwortlichkeiten zu definieren und diese Definitionen auf bequeme Weise zu verstehen, während Sie versuchen, sie zu verarbeiten.
Java-ish OO ist eine halbe Lösung für diese Probleme, die zufällig den Beliebtheitswettbewerb gewonnen haben. Da es sich um den gleichen Mechanismus handelt, den Java-Benutzer bei kleinen Problemen anwenden, die durch eine unterbewertete Sprache verursacht werden, sieht es eher nach einer magischen Lösung für alles aus, als nach einer Möglichkeit, organisiert zu bleiben. Leute, die mit funktionaler Programmierung vertraut sind, bevorzugen andere Lösungen, wie CLOS- oder Haskell-Typenklassen oder Template-Metaprogrammierung, wenn sie in C ++ stecken bleiben, oder verwenden (wie ich, arbeiten täglich in C #) OO, aber freuen sich nur nicht darüber .
quelle
OOP versucht, reale Konzepte in Bezug auf Objekte und Interaktionen zwischen ihnen zu modellieren. Als Menschen neigen wir dazu, die Welt in Bezug auf Objekte zu verarbeiten. Die Welt ist voll von Objekten, die bestimmte Eigenschaften haben und Dinge tun können, wie mit anderen Objekten zu interagieren. OOP erlaubt es, die Welt in ähnlichen Begriffen zu modellieren. Beispielsweise,
Aber ein Auto kann sich nicht von alleine bewegen, es braucht eine Person, die es fährt - Interaktion zwischen Objekten.
quelle
OOP = Datenstrukturen + Nachrichtenübermittlung + Vererbung, alles logische Entwicklungen in Programmiermodellen.
OOP kann (von Programmierern) in ungefähr 90 Sekunden verstanden werden (siehe mein Profil für einen Link). Die Konzepte sind sehr einfach.
Wie es anzuwenden ist, ist eine andere Sache. Nur weil Sie wissen, wie man einen Hammer schwingt, heißt das nicht, dass Sie wissen, wie man ein Haus entwirft und baut. ;-)
quelle
Ich habe vor einiger Zeit einen Blog-Beitrag geschrieben, der hilfreich sein könnte: Procedural vs. OOP Explained .
quelle
So wie ich es zuerst verstanden habe, ist es:
Vor der objektorientierten Programmierung hatten Sie die strukturierte Programmierung . Alles dreht sich um den Prozess. Die erste Frage, die Sie sich stellen müssen, lautet: " Was möchte ich mit den Informationen machen? ".
Bei der objektorientierten Programmierung stehen die Daten im Mittelpunkt. Die erste Frage, die Sie sich stellen müssen, ist " Hexeninformationen, mit denen ich mich befassen muss? ". Dies erleichtert die Abstraktion.
quelle
Da Sie Strukturen und Funktionszeiger verstehen und Sie Strukturen mit Funktionszeigern verstehen, würde ich aus Ihrer Sicht objektorientierte Programmierung einfach als "Programmierung unter starker Verwendung von Strukturen mit Funktionszeigern" definieren. Es programmiert immer noch im traditionellen Sinne - es sind alles Daten und Code, der auf die Daten einwirkt. Der Unterschied besteht einfach darin, wie all diese Informationen definiert sind und wie Sie sich ihrer Definition nähern.
Vielleicht ist eine übermäßige Vereinfachung, dass die traditionelle Programmierung "Code mit einigen Datenstrukturen" und die objektorientierte Programmierung "Datenstrukturen mit einem gewissen Code" ist. Beide haben noch Datenstrukturen und beide haben noch Code. Objektorientierte Programmierung ist also nichts anderes als das Definieren von Datentypen im Voraus und das Durchsetzen von Verträgen für die Kommunikation über Funktionssätze.
Wie Sie bereits bemerkt haben, gibt es eine große Anzahl von Anwendungen, für die dies keine gute Möglichkeit ist, eine Lösung zu implementieren. Sie scheinen in einer Welt zu leben, die überwiegend aus solchen Anwendungen besteht. In Ihrem Blogbeitrag erwähnen Sie die Umsetzung des Problems "99 Flaschen Bier" (Ihr "Lieblingsprogrammierungsschaufenster"). 99 Flaschen Bier gehören sicherlich zu dieser Kategorie. Der Versuch, die objektorientierte Programmierung anhand von Implementierungen von 99 Flaschen Bier zu verstehen, ähnelt dem Versuch, die Hochhausarchitektur anhand eines Baumhauses zu verstehen. Selbst ein sehr gut gebautes Baumhaus kann Ihnen nur so viel beibringen.
TL; DR: OO-Programmierung ist wie herkömmliche Programmierung, außer dass Sie sich mehr auf die Definition der Datenstrukturen konzentrieren und diese Datenstrukturen über Funktionszeiger miteinander kommunizieren.
quelle
Ich denke, die Wikipedia-Seite ist ein guter Ort, um die Grundlagen zu erhalten:
http://en.wikipedia.org/wiki/Object-oriented_programming
Grundsätzlich ist die Idee, dass die prozedurale Programmierung, die OOP verbessern wollte, sich auf die zu modellierenden Prozesse konzentriert. OOP wechselt zu einem Modell, bei dem der Fokus auf den "Dingen" liegt, die Sie modellieren, und die Prozesse und Daten dieser Dinge in diesen Dingen enthalten sind.
Nehmen wir als Beispiel an, Sie entwerfen eine Anwendung zum Verfolgen einer Aufgabenliste. Bei der prozeduralen Programmierung handelt es sich bei den Entitäten auf oberster Ebene im Modell um die Prozesse, die ausgeführt werden, z Überlegen Sie, für welche Daten und Prozesse der Task verantwortlich sein sollte. Konzentrieren Sie sich dann auf die Objekte, mit denen Task interagieren soll, z. B. auf eine Notiz oder etwas, wenn Sie Notizen zu Aufgaben erstellen möchten.
Ich hoffe das hilft. Lesen Sie einfach weiter und sehen Sie sich den Code an, und er wird plötzlich "klicken". Das war meine Erfahrung.
quelle