Frage

Notiz: Diese Frage ist ein bearbeiteter Auszug aus a Blog -Posting Ich habe vor ein paar Monaten geschrieben. Nach dem Platzieren eines Links zum Blog in a Kommentar Auf Programmierern. Dieser Beitrag ist mein beliebtestes, da die Leute anscheinend "Ich bekomme keine objektorientierte Programmierung in Google viel. 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 mit der Nase in der Luft „Objekt“ und „objektorientiert“ sagt. Sie erhalten auch keine gute Definition von jemandem, der nur objektorientierte Programmierung getan hat. Niemand, der sowohl prozedurale als auch objektorientierte Programmierung versteht, hat mir jemals eine konsequente Vorstellung davon gegeben, was ein objektorientiertes Programm tatsächlich tut.

Kann mir bitte jemand seine Ideen für die Vorteile der objektorientierten Programmierung geben?

War es hilfreich?

Lösung

Stellen Sie sich Software als Maschine oder Montagelinie vor, die im Computer vorhanden ist. Einige Rohstoffe und Komponenten werden in die Maschine eingespeist und folgt einer Reihe von Verfahren, um sie in ein Endprodukt zu verarbeiten. Die Verfahren werden so eingerichtet, dass sie in einer bestimmten Reihenfolge einen bestimmten Vorgang auf einem Rohstoff oder einer bestimmten Komponente für einen bestimmten Parametersatz (z. B. Zeit, Temperatur, Entfernung usw.) ausführen. Wenn die Details der zu ausgeführten Operation falsch waren oder die Sensoren des Geräts nicht korrekt kalibriert sind oder ein Rohstoff oder eine Komponente nicht innerhalb der erwarteten Qualitätsstandards nicht in den erwarteten Qualitätsstandard wie erwartet.

Eine solche Maschine ist in ihrem Betrieb und akzeptablen Eingaben sehr starr. Maschinen stellen weder die Intelligenz der Designer noch ihre aktuelle Betriebsumgebung in Frage. Es wird weiterhin Verfahren folgen, solange es gerichtet ist. Selbst wenn eine Änderung der Rohstoffe oder Komponenten einen dramatischen Einfluss auf das, was in späteren Vorgängen passiert ist, haben könnte, würde die Maschine ihre Verfahren dennoch ausführen. Der Prozess müsste überprüft werden, um festzustellen, welche Änderungen an den Verfahren erforderlich waren, 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 ausgeführten Vorgänge oder ihrer Bestellung erfordern. Obwohl die für die Produktion verantwortlichen Produktion schnell erfuhren, wie wichtig es ist, Operationen so weit wie möglich zu isolieren, um unerwünschte Effekte zwischen ihnen zu reduzieren, werden viele Annahmen über die Bedingungskomponenten getroffen, in denen sie sich verarbeiten. Annahmen, die möglicherweise erst erkannt werden, wenn sich das Endprodukt in einer anderen Betriebsumgebung in den Händen des Benutzers befindet.

So ist prozedurale Programmierung.

Was Objektorientierung liefert, ist eine Möglichkeit, die Annahmen des Zustands der Komponenten zu beseitigen. Somit sind die Operationen, die an dieser Komponente ausgeführt werden sollen und wie sie in das Endprodukt integriert werden können. Mit anderen Worten, OOP ist wie die Prozessdetails für den Umgang mit einer bestimmten Komponente und das Verschenken einer kleineren Maschine. Die für den Prozess verantwortliche größere Maschine teilt der komponentenspezifischen Maschine mit, die von der von ihm ausgeführten Vorgänge ausgeführt werden soll.

In Bezug auf die Vorteile der Objektorientierung gegenüber nicht objektorientierter Software:

  • Komponentenspezifisches Verhalten - Details zum Umgang mit einer bestimmten Komponente In der Verantwortung der kleineren Komponentenspezifischen Maschine wird jederzeit sichergestellt, dass die Komponente die Maschine angemessen tut.
  • Polymorphe Expressionen - Da Komponentenspezifische Maschinen Operationen ausführen, die auf seine bestimmte Komponente zugeschnitten sind, kann dieselbe Nachricht, die an verschiedene Maschinen gesendet wird, unterschiedlich handeln.
  • Typ Abstraktion - Es ist oft sinnvoll, dass verschiedene Arten von Komponenten für die Vorgänge, die ihre Maschinen ausführen, denselben Vokabular verwenden.
  • Trennung von Bedenken - Das Verlassen der komponentenspezifischen Details an ihre Maschinen bedeutet, dass die Prozessmaschine nur die allgemeineren, größeren Bedenken ihres Prozesses und die Daten zur Verwaltung erfordern. Außerdem ist es weniger wahrscheinlich, dass Änderungen in anderen Komponenten beeinflusst werden.
  • Anpassungsfähigkeit - Komponenten, die sich auf ihren Spezialbereich konzentrieren, können an unvorhergesehene Verwendung angepasst werden, indem sie einfach die von ihnen verwendeten Komponenten ändern oder einer anderen Prozessmaschine zur Verfügung stellen.
  • Code -Wiederverwendung - Komponenten mit einem engen Fokus und einer größeren Anpassungsfähigkeit können ihre Entwicklungskosten nutzen, indem sie häufiger eingesetzt werden.

Andere Tipps

Aus Ihrem Blog sind Sie so aus, dass Sie mit der imperativen und funktionalen Programmierung vertraut sind und dass Sie mit den grundlegenden Konzepten vertraut sind macht es nützlich. Ich werde versuchen, dieses Wissen zu erklären und zu hoffen, dass es Ihnen hilfreich ist.

OOP ist im Kern eine Möglichkeit, das imperative Paradigma zu nutzen, um eine bessere Komplexität zu verwalten, indem "intelligente" Datenstrukturen erstellt werden, die die Problemdomäne modellieren. In einem (Standard prozeduralen nicht-objektorientierten) Programm haben Sie zwei grundlegende Dinge: Variablen und Code, die wissen, was Sie damit anfangen sollen. Der Code nimmt Eingaben vom Benutzer und verschiedenen anderen Quellen ein, speichert ihn in Variablen, arbeitet darauf und erstellt Ausgabedaten, die an den Benutzer oder an verschiedene andere Standorte geleitet werden.

Objektorientierte Programmierung ist eine Möglichkeit, Ihr Programm zu vereinfachen, indem Sie dieses grundlegende Muster aufnehmen und in kleinerem Maßstab wiederholen. Genau wie ein Programm ist eine große Sammlung von Daten mit Code, die weiß, was damit zu tun ist, jedes Objekt ist ein kleines Datenstück, das an Code gebunden ist, das weiß, was sie damit machen sollen.

Indem Sie die Problemdomäne in kleinere Stücke zerlegen und sicherstellen, dass so viele Daten wie möglich direkt an Code gebunden sind, der weiß, was Sie damit anfangen sollen, erleichtern Sie es viel einfacher, über den Prozess als Ganzes und auch über die Subs zu argumentieren Probleme, die den Prozess ausmachen.

Durch das Gruppieren von Daten in Objektklassen können Sie den Code im Zusammenhang mit diesen Daten zentralisieren und relevante Code sowohl zu finden als auch zum Debuggen erleichtern. Und indem Sie die Daten hinter Zugriffsspezifizierern zusammenfassen und nur durch Methoden (oder Eigenschaften, wenn Ihre Sprache) darauf zugreifen, verringern Sie das Potenzial für Datenbeschädigung oder den Verletzung von Invarianten erheblich.

Mithilfe von Vererbung und Polymorphismus können Sie bereits vorhandene Klassen wiederverwenden und sie an Ihre spezifischen Anforderungen anpassen, ohne die Originale zu ändern oder alles von Grund auf neu zu schreiben. (Die ein was du niemals tun solltest, wenn Sie es vermeiden können.) Seien Sie einfach vorsichtig, dass Sie Ihr Basisobjekt verstehen, oder Sie könnten am Ende enden Mörder Kängurus.

Für mich sind dies die grundlegenden Prinzipien der objektorientierten Programmierung: Komplexitätsmanagement, Code-Zentralisierung und verbesserte Modellierung der Problem-Domänen durch die Erstellung von Objektklassen, Vererbung und Polymorphismus sowie erhöhte Sicherheit, ohne die Kraft oder Kontrolle durch die Verwendung von Einkapselung und Einkapselung zu opfern Eigenschaften. Ich hoffe, dies hilft Ihnen zu verstehen, warum so viele Programmierer es nützlich finden.

Bearbeiten: Als Antwort auf Joels Frage in den Kommentaren,

Können Sie erklären, was ein "objektorientiertes Programm" enthält (abgesehen von diesen ausgefallenen Definitionen, die Sie skizziert haben), das sich grundsätzlich von einem imperativen Programm unterscheidet? Wie kommst du "den Ball ins Rollen?"

Ein kleiner Haftungsausschluss hier. Mein Modell von "ein objektorientiertes Programm" ist im Grunde das Delphi-Modell, das dem C#/. Net-Modell sehr ähnlich ist, da sie von ehemaligen Mitgliedern des Delphi-Teammitglieds erstellt wurden. Was ich hier sage, gilt möglicherweise nicht so viel in anderen OO -Sprachen.

Ein objektorientiertes Programm ist eines, in dem die gesamte Logik um Objekte strukturiert ist. Natürlich muss dies irgendwo Bootstraß erfolgen. Ihr typisches Delphi -Programm enthält Initialisierungscode, das ein Singleton -Objekt nennt Application. Zu Beginn des Programms ruft es auf Application.Initialize, dann ein Anruf bei Application.CreateForm Für jede Form möchten Sie von Anfang an und dann in den Speicher laden, und dann und dann Application.Run, Dies zeigt das Hauptformular auf dem Bildschirm an und startet die Eingabe-/Ereignisschleife, die den Kern aller interaktiven Computerprogramme bildet.

Anwendung und Ihre Formulare Umfrage für eingehende Ereignisse aus dem Betriebssystem und übersetzen Sie sie in Methodenaufrufe Ihres Objekts. Eine Sache, die sehr häufig ist, ist die Verwendung von Ereignishandlern oder "Delegierten" in .NET-Speak. Ein Objekt hat eine Methode, in der lautet: "Do X und Y, aber auch prüft, ob dieser bestimmte Ereignishandler zugewiesen ist, und nennen Sie es, wenn es so ist." Ein Ereignishandler ist ein Methodenzeiger-ein sehr einfacher Verschluss, der einen Verweis auf die Methode und einen Verweis auf die Objektinstanz enthält-, mit dem das Verhalten von Objekten erweitert wird. Wenn ich beispielsweise ein Knopfobjekt in meinem Formular habe, passe ich sein Verhalten an, indem ich einen Onclick -Ereignis -Handler anschließe, wodurch ein anderes Objekt beim Klicken der Schaltfläche eine Methode ausführt.

In einem objektorientierten Programm wird der größte Teil der Arbeit erledigt, indem Objekte mit bestimmten Verantwortlichkeiten definiert und miteinander verbunden werden, entweder über Methodenzeiger oder durch ein Objekt, das direkt eine Methode aufruft, die in der öffentlichen Schnittstelle eines anderen Objekts definiert ist. (Und jetzt sind wir zurück zur Kapselung.) Dies ist eine Idee, dass ich kein Konzept von Rücken hatte, bevor ich OOP -Kurse im College besuchte.

Ich denke, OOP ist im Grunde nur ein Name, der etwas gegeben wurde, zu dem Sie auf dem Weg so versucht waren, wie ich es war.

Als ich ein Babyprogrammierer war, sogar in Forran, gab es so etwas wie einen Zeiger auf eine Unterroutine. Es ist wirklich nützlich, einen Zeiger an eine Unterroutine als Argument an eine andere Unterroutine übergeben zu können.

Dann wäre das nächste, was wirklich nützlich wäre, darin, einen Zeiger auf eine Unterroutine in einem Datensatz einer Datenstruktur zu speichern. Auf diese Weise könnten Sie sagen, dass der Datensatz "weiß", wie man Operationen für sich selbst macht.

Ich bin mir nicht sicher, ob sie das jemals in Forran aufgebaut haben, aber es ist in C und seinen Nachkommen leicht zu tun.

Es ist also eine einfache und nützliche Idee, dass Sie möglicherweise versucht waren, selbst zu tun, und in neueren Sprachen einfacher zu tun, auch wenn einige Leute daraus einen riesigen Zug voller beängstigender Schlagworte verwandelten.

Es gibt verschiedene Arten von OO -Systemen, und es ist schwierig, eine Definition zu erhalten, auf die sich jeder einigen wird. Anstatt zu versuchen zu zeigen, wie Javas OO dem gemeinsamen Lisp -Objektsystem ähnlich ist, werde ich Schritt für Schritt mit etwas konventionelleren beginnen.

Angenommen, Sie haben viele Objekte, die als verstreute Daten vorhanden sind. Punkte können zum Beispiel Elemente in einem x, einem y und einem z -Array sein. Um einen Punkt selbst zu berücksichtigen, ist es sinnvoll, alle Daten in etwas wie ein C zusammenzubringen struct.

Für jedes Datenobjekt haben wir nun die Daten zusammen. In einem Verfahrensprogramm ist der Code jedoch verstreut. Angenommen, wir haben es mit geometrischen Formen zu tun. Es gibt eine große Funktion, um Formen zu zeichnen, und es muss über alle Formen informiert werden. Es gibt eine große Funktion, um Bereich zu finden, und eine andere für den Umfang. Der Code für einen Kreis wird durch mehrere Funktionen verstreut. Um eine andere Art von Form hinzuzufügen, müssen wir wissen, welche Funktionen geändert werden sollen. In einem objektorientierten System sammeln wir die Funktionen in die gleiche Art (Dinge (class) als Daten. Wenn wir uns also den gesamten Kreiscode ansehen wollen, ist er dort in der Circle Definition und wenn wir a hinzufügen wollen Quartercircle Wir schreiben einfach seine Klasse und wir haben den Code.

Eine Seite davon ist, dass wir Klasseninvarianten beibehalten können, Dinge, die für jedes Mitglied der Klasse wahr sind. Indem wir Code außerhalb der Klasse von direktem Durcheinander mit Klassendatenmitgliedern einschränken, haben wir alle Code, die die Klassendaten an einem Ort ändern können, und wir können bestätigen, dass er nichts Verrissees tut (wie ein Dreieck mit einem Bein haben länger als die anderen beiden zusammen). Dies bedeutet, dass wir uns auf einige Eigenschaften jedes Mitglieds der Klasse verlassen können, und müssen nicht überprüfen, ob ein Objekt bei jedem Verwendung gesund ist.

Der Hauptvorteil ist mit Vererbung und Polymorphismus verbunden. Durch Definieren all dieser verschiedenen Formen als Unterklassen einer Klasse genannt Shape, Wir können unseren Code manipulieren lassen ShapeS, und es ist die Aufgabe der Form -Unteroben, alles zu tun, was von den Manipulationen erforderlich ist. Dies bedeutet, dass wir den alten getesteten Code nicht berühren müssen, wenn wir neue Formen hinzufügen oder das Verhalten älterer verfeinern. Wir haben automatisch einen alten Code, der den neuen Code direkt nutzen kann. Anstatt den kontrollierenden Code auf all die verschiedenen möglichen Formen aufmerksam zu machen und Funktionen aufrechtzuerhalten, die sich der verschiedenen möglichen Formen bewusst sind, beschäftigen wir uns lediglich mit Formen und ihren Eigenschaften, während wir beibehalten werden, während wir aufrechterhalten werden Shape Unterklassen. Dies vereinfacht den Kontrollcode.

Wir haben hier mehrere Vorteile. Da wir Klasseninvarianten haben, können wir über größere Datenobjekte auf die gleiche Weise zu integrierten Typen argumentieren, was bedeutet, dass wir komplexe Konzepte häufig in einfachere Aufteils aufteilen können. Da der Kreiscode weitgehend in enthalten ist Circle, Wir haben die Lokalität verstärkt. Da es keine Konzepte eines Kreises gibt, der an verschiedenen Orten durch verschiedene Funktionen verstreut ist, erhalten wir weniger eine Kopplung zwischen Routinen und müssen sich keine Sorgen machen, sie synchron zu halten. Da der Unterricht tatsächlich Typen ist, können wir das vorhandene Typsystem nutzen, um die inkompatible Verwendung unserer Klassen zu fangen.

OO hat viele verschiedene Definitionen, ja. Ich bin sicher, Sie können viele davon alleine finden. Ich persönlich mag Rees re: oo Um sie zu verstehen. Ich vermute, Sie haben das schon gelesen, seit Sie Paul Graham zitieren. (Ich empfehle es jedem, der sich für OO interessiert.) Ich werde hier mehr oder weniger die Java -Definition achten {1,2,3,7,8,9}.

Die Frage nach dem Nutzen von OO, insbesondere der Art und Weise, wie ich mich ihr nähere, verdient eine viel größere Antwort mit ein paar tausend Codezeilen (teilweise, um nicht nur eine Reihe 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, z. B. etwa ein paar hundert Zeilen. Insbesondere OO -Sprachen ohne gute funktionale Einflüsse machen es wirklich schmerzhaft, einfache Dinge mit irgendeiner Art von Sammlung oder irgendetwas zu erledigen, was viele Datentypen benötigt. Hier kommen die meisten Designmuster ins Spiel. Sie sind Pflaster in der geringen Kraft der zugrunde liegenden Sprache.

Bei etwa tausend Zeilen fällt es schwieriger, alle Vorgänge und Datenstrukturen und ihre Beziehung zu verfolgen. Es hilft an diesem Punkt, eine Möglichkeit zu haben, Datenstrukturen und Operationen explizit zu organisieren, Modulgrenzen zu ziehen und Verantwortlichkeiten zu definieren und eine bequeme Möglichkeit zu haben, diese Definitionen zu verstehen, während Sie versuchen, gegen sie zu programmieren.

Java-ish OO ist eine halber Lösung für diese Probleme, die zufällig den Popularitätswettbewerb gewonnen hat. Da es sich um den gleichen Mechanismus handelt, den Java -Leute auf die kleinen Probleme einer unterverträchten Sprache anwenden, sieht es eher wie eine magische Lösung für alles aus als nur eine Möglichkeit, organisiert zu bleiben. Personen, die mit funktionaler Programmierung vertraut sind, bevorzugen andere Lösungen wie Clos oder Haskells Typklassen oder Vorlagen -Metaprogrammierung, wenn sie in C ++ stecken, oder (wie ich arbeite täglich in C#) OO, aber lassen Sie sich einfach nicht so begeistert darüber aufregen .

Oop Versuche, 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 wie interagieren mit anderen Objekten tun können. OOP ermöglicht es, die Welt ähnlich zu modellieren. Zum Beispiel,

  • Person ist ein Objekt. Eine Person hat einige Eigenschaften wie Alter und Geschlecht. Eine Person kann Dinge tun: essen, schlafen, ein Auto fahren.
  • Das Auto ist auch ein Objekt (obwohl unterschiedlich). Es gibt auch Eigenschaften wie Make, Modell und Jahr. Ein Auto kann Dinge tun: bewegen.

Aber ein Auto kann sich nicht selbst bewegen, es muss eine Person benötigen, um es zu fahren - Interaktion zwischen Objekten.

OOP = Datenstrukturen + Nachrichtenübergabe + Vererbung, die alle logische Entwicklung in Programmiermodellen sind.

OOP kann (von Programmierern) in etwa 90 Sekunden verstanden werden (siehe mein Profil für einen Link). Die Konzepte sind sehr einfach.

Wie man es anwendet, ist eine andere Sache. Nur weil Sie wissen, wie man einen Hammer schwingt, bedeutet nicht, dass Sie wissen, wie man ein Haus entwirft und baut. ;-)

Ich habe vor einiger Zeit einen Blog -Beitrag geschrieben, in dem Sie möglicherweise hilfreich finden: Prozedural gegen oop erklärt.

Die Art, wie ich es zuerst verstanden habe, ist:

Vor einer objektorientierten Programmierung hatten Sie Strukturierte Programmierung. Alles dreht sich um den Prozess. Die erste Frage, die Sie sich stellen müssen, ist "Was möchte ich mit den Informationen anfangen?".

Bei objektorientierter Programmierung dreht sich sie um die Daten. Die erste Frage, die Sie sich stellen müssen, ist "Hexeninformationen, mit denen ich mich befassen muss?"Dies erleichtert die Abstraktion.

Da Sie Strukturen verstehen und Funktionszeiger verstehen und Strukturen mit Funktionszeiger verstehen, würde ich aus Ihrer Sicht die objektorientierte Programmierung als "Programmierung, mit starker Verwendung von Strukturen mit Funktionszeiger" definieren. Es ist immer noch programmiert im traditionellen Sinne - es sind alle Daten und Code, die auf die Daten wirken. Der Unterschied ist einfach, wie all diese Informationen definiert werden und wie Sie sich nähern, um sie zu definieren.

Möglicherweise ist eine Übereinstimmung, dass die herkömmliche Programmierung "Code mit einigen Datenstrukturen" ist und objektorientierte Programmierung "Datenstrukturen, mit etwas Code". Beide haben noch Datenstrukturen und beide haben noch Code. Die objektorientierte Programmierung ist also nichts anderes als das Definieren von Datentypen im Voraus und die Durchsetzung von Verträgen für die Art und Weise, wie sie über Funktionssätze kommunizieren.

Wie Sie beobachtet haben, gibt es eine große Klasse von Anwendungen, für die dies keine großartige Möglichkeit ist, eine Lösung zu implementieren. Sie scheinen in einer Welt zu leben, die überwiegend aus solchen Anwendungen besteht. In Ihrem Blog -Beitrag erwähnen Sie, dass Sie die Implementierungen des Problems "99 Flaschen Bier" (Ihr "Lieblings -Programming -Showcase") betrachten. 99 Flaschen Bier sind sicherlich Teil dieser Kategorie. Der Versuch, die objektorientierte Programmierung zu verstehen, indem es die Implementierungen von 99 Flaschen Bier betrachtet, ist ein bisschen wie der Versuch, Hochhausarchitektur durch Betrachtung eines Baumhauses zu verstehen. Selbst ein sehr gut gebautes Baumhaus kann Ihnen nur so viel beibringen.

TL; DR: OO -Programmierung ist wie eine herkömmliche Programmierung, außer dass Sie sich mehr von Ihrem Aufwand bei der Definition der Datenstrukturen im Voraus konzentrieren, und Sie haben diese Datenstrukturen über Funktionszeiger miteinander kommunizieren.

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 zu verbessern versuchte, sich auf die modellierten Prozesse konzentrierte. OOP verschiebt sich zu einem Modell, bei dem sich der Fokus auf den "Dingen" befindet, die Sie modellieren, und die Prozesse und Daten dieser Dinge sind in diesen Dingen enthalten.

Nehmen wir also beispielsweise an, Sie haben eine Anwendung entworfen, um eine Aufgabenliste zu verfolgen. Bei der prozeduralen Programmierung wären Ihre Top -Ebenen im Modell die Prozesse, die auftreten, z. B. das Erstellen einer Aufgabe, das Entfernen einer Aufgabe, das Ändern der Aufgabeninformationen usw. In einem OOP -Modell konzentrieren Sie Überlegen Sie, für welche Daten und Prozesse diese Aufgabe verantwortlich sein sollten. Konzentrieren Sie sich dann darauf, mit welcher anderen Objektaufgabe interagieren sollten, wie möglicherweise eine Notiz oder etwas, wenn Sie Notizen über Aufgaben aufbewahren möchten.

Ich hoffe das hilft. Lesen Sie einfach weiter darüber und schauen Sie sich den Code an, und es wird plötzlich "klicken". Das war meine Erfahrung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top