Warum die Behauptung, dass C#-Leute keine objektorientierte Programmierung erhalten?(vs. klassenorientiert)

StackOverflow https://stackoverflow.com/questions/52092

  •  09-06-2019
  •  | 
  •  

Frage

Das erregte gestern Abend meine Aufmerksamkeit.

Spätestens ALT.NET-Podcast Scott Bellware erläutert, wie im Gegensatz zu Ruby Sprachen wie C#, Java et al.sind nicht wirklich objektorientiert, sondern entscheiden sich für den Ausdruck „klassenorientiert“.Sie sprechen über diese Unterscheidung sehr vage, ohne ausführlich ins Detail zu gehen oder die Vor- und Nachteile ausführlich zu diskutieren.

Was ist hier der wirkliche Unterschied und wie wichtig ist er?Welche anderen Sprachen sind dann „objektorientiert“?Es klang ziemlich interessant, aber ich möchte Ruby nicht lernen müssen, nur um zu wissen, was mir gegebenenfalls fehlt.

Aktualisieren:Nachdem ich einige der Antworten unten gelesen habe, scheint es, als wären sich die Leute im Allgemeinen darin einig, dass es sich um Duck-Typing handelt.Ich bin mir jedoch nicht sicher, ob ich die Behauptung immer noch verstehe, dass sich dadurch letztendlich so viel ändert.Vor allem, wenn Sie bereits eine ordnungsgemäße TDD mit loser Kopplung durchführen, bla bla bla.Kann mir jemand ein Beispiel für eine wunderbare Sache zeigen, die ich mit Ruby machen könnte, die ich mit C# nicht machen kann und die diesen anderen Oop-Ansatz veranschaulicht?

War es hilfreich?

Lösung

Die Kommentare zum Duck-Typing hier sind eher auf die Tatsache zurückzuführen, dass Ruby und Python mehr sind dynamisch als C#.Es hat nicht wirklich etwas mit seiner OO-Natur zu tun.

Was Bellware (glaube ich) damit meinte, ist, dass in Ruby alles ein Objekt ist.Sogar eine Klasse.Eine Klassendefinition ist eine Instanz eines Objekts.Daher können Sie zur Laufzeit Verhalten hinzufügen/ändern/entfernen.

Ein weiteres gutes Beispiel ist, dass NULL ebenfalls ein Objekt ist.In Ruby ist buchstäblich alles ein Objekt.Ein so tiefes OO in seinem gesamten Wesen ermöglicht einige unterhaltsame Metaprogrammierungstechniken wie method_missing.

Andere Tipps

In einer objektorientierten Sprache werden Objekte durch die Definition von Objekten und nicht durch Klassen definiert, obwohl Klassen einige nützliche Vorlagen für spezifische Standarddefinitionen einer bestimmten Abstraktion bereitstellen können.In einer klassenorientierten Sprache, wie zum Beispiel C#, müssen Objekte durch Klassen definiert werden, und diese Vorlagen werden normalerweise vorgefertigt, gepackt und vor der Laufzeit unveränderlich gemacht.Diese willkürliche Einschränkung, dass Objekte vor der Laufzeit definiert werden müssen und dass die Definitionen von Objekten unveränderlich sind, ist kein objektorientiertes Konzept;es ist klassenorientiert.

Meiner Meinung nach definiert es „objektorientiert“ wirklich zu sehr, aber worauf sie sich beziehen, ist, dass Ruby im Gegensatz zu C#, C++, Java usw. keinen Gebrauch davon macht definieren eine Klasse – man arbeitet eigentlich immer nur direkt mit Objekten.Umgekehrt definieren Sie beispielsweise in C# Klassen dass du dann musst instanziieren über das Schlüsselwort new in ein Objekt umgewandelt werden.Der entscheidende Punkt ist, dass Sie müssen erklären eine Klasse in C# oder beschreiben Sie sie.Darüber hinaus gilt in Ruby: alles – gerade Zahlen zum Beispiel – ist ein Objekt.Im Gegensatz dazu behält C# weiterhin das Konzept eines Objekttyps und eines Werttyps bei.Dies verdeutlicht meiner Meinung nach tatsächlich den Punkt, den sie zu C# und anderen ähnlichen Sprachen sagen – Objekt Typ und Wert Typ implizieren a Typ System, was bedeutet, dass Sie ein komplettes System von haben beschreibend statt nur mit Objekten zu arbeiten.

Vom Konzept her denke ich OO Design ist es, was heutzutage die Abstraktion zur Bewältigung der Komplexität in Softwaresystemen bereitstellt.Die Sprache ist ein Werkzeug zur Implementierung eines OO-Designs – einige machen es natürlicher als andere.Ich würde immer noch argumentieren, dass C# und die anderen einer allgemeineren und umfassenderen Definition nach immer noch gelten objektorientierte Sprachen.

Es gibt drei Säulen von OOP

  1. Verkapselung
  2. Nachlass
  3. Polymorphismus

Wenn eine Sprache diese drei Dinge kann, ist sie eine OOP-Sprache.

Ich bin mir ziemlich sicher, dass das Argument der Sprache

OO wird manchmal definiert als nachrichtenorientiert.Die Idee ist, dass ein Methodenaufruf (oder Eigenschaftszugriff) tatsächlich eine an ein anderes Objekt gesendete Nachricht ist.Wie das empfangende Objekt die Nachricht verarbeitet, ist vollständig gekapselt.Oft entspricht die Nachricht einer Methode, die dann ausgeführt wird, aber das ist nur ein Implementierungsdetail.Sie können beispielsweise einen Catch-All-Handler erstellen, der unabhängig vom Methodennamen in der Nachricht ausgeführt wird.

Statisches OO wie in C# verfügt nicht über diese Art der Kapselung.Eine Massage hat einer vorhandenen Methode oder Eigenschaft entsprechen, andernfalls wird sich der Compiler beschweren.Dynamische Sprachen wie Smalltalk, Ruby oder Python unterstützen jedoch „nachrichtenbasiertes“ OO.

In diesem Sinne sind C# und andere statisch typisierte OO-Sprachen also keine echten OO-Sprachen, da ihnen die „echte“ Kapselung fehlt.

Aktualisieren:Es ist die neue Welle.was darauf hindeutet, dass alles, was wir bisher getan haben, passe ist.Scheint in Podcasts und Büchern ziemlich viel Auftrieb zu geben.Vielleicht haben Sie das gehört.

Bisher haben wir uns mit statischen Klassen beschäftigt und nicht entfesselt die Kraft der objektorientierten Entwicklung.Wir haben "klassenbasierte Entwickler" gemacht. Klassen sind fest/statische Vorlagen, um Objekte zu erstellen.Alle Objekte einer Klasse sind gleichwertig.

z.B.Nur um zu veranschaulichen, worüber ich geplappert habe ...Lassen Sie mich einen Ruby-Codeausschnitt aus dem PragProg-Screencast ausleihen, den ich gerade ansehen durfte.„Prototypbasierte Entwicklung“ verwischt die Grenze zwischen Objekten und Klassen.es gibt keinen Unterschied.

animal = Object.new                  # create a new instance of base Object

def animal.number_of_feet=(feet)     # adding new methods to an Object instance. What?
  @number_of_feet = feet
end
def animal.number_of_feet
  @number_of_feet
end

cat = animal.clone          #inherits 'number_of_feet' behavior from animal
cat.number_of_feet = 4

felix = cat.clone           #inherits state of '4' and behavior from cat
puts felix.number_of_feet   # outputs 4

Die Idee dahinter ist, dass es sich dabei um eine leistungsfähigere Methode zur Vererbung von Zustand und Verhalten handelt als die herkömmliche klassenbasierte Vererbung.Es gibt Ihnen mehr Flexibilität und Kontrolle in bestimmten „besonderen“ Szenarien (die ich noch nicht verstanden habe).Dies ermöglicht Dinge wie Mix-Ins (Wiederverwendung von Verhalten ohne Klassenvererbung).

Indem es die Grundprinzipien unserer Denkweise über Probleme in Frage stellt, ist „wahres OOP“ in gewisser Weise wie „die Matrix“ ...Du machst WTF in einer Schleife weiter.Wie dieser..Dabei kann die Basisklasse von Container entweder ein Array oder ein Hash sein, je nachdem, auf welcher Seite von 0,5 die generierte Zufallszahl liegt.

class Container < (rand < 0.5 ? Array : Hash)
end

Ruby, Javascript und die neue Brigade scheinen hier Vorreiter zu sein.Da bin ich immer noch nicht dran...Ich lese dieses neue Phänomen nach und versuche, es zu verstehen.Scheint mächtig zu sein..zu mächtig..Nützlich?Ich muss meine Augen etwas mehr öffnen.Interessante Zeiten..diese.

Ich habe mir nur die ersten 6-7 Minuten des Podcasts angehört, der Ihre Frage ausgelöst hat.Wenn sie sagen wollen, dass C# keine rein objektorientierte Sprache ist, dann ist das tatsächlich richtig.Alles in C# ist kein Objekt (zumindest die Grundelemente sind es nicht, obwohl durch Boxen ein Objekt erstellt wird, das denselben Wert enthält).In Ruby ist alles ein Objekt.Daren und Ben scheinen in ihrer Diskussion über „Duck-Typing“ alle Grundlagen abgedeckt zu haben, daher werde ich es nicht wiederholen.

Ob dieser Unterschied (alles ein Objekt im Vergleich zu allem, was kein Objekt ist) wesentlich/signifikant ist oder nicht, ist eine Frage, die ich nicht ohne weiteres beantworten kann, da ich nicht über ausreichende Kenntnisse in Ruby verfüge, um es mit C# zu vergleichen.Diejenigen unter Ihnen, die sich mit Smalltalk auskennen (ich nicht, obwohl ich es wünschte), haben die Ruby-Bewegung wahrscheinlich mit einiger Belustigung betrachtet, da sie vor 30 Jahren die erste reine OO-Sprache war.

Vielleicht spielen sie auf den Unterschied zwischen Ententypisierung und Klassenhierarchien an?

Wenn es wie eine Ente läuft und wie eine Ente quakt, tun Sie einfach so, als wäre es eine Ente, und treten Sie es.

In C#, Java usw.Der Compiler macht viel Aufhebens um:Dürfen Sie diesen Vorgang an diesem Objekt durchführen?

Objektorientiert vs.Klassenorientiert könnte daher bedeuten:Kümmert sich die Sprache um Objekte oder Klassen?

Zum Beispiel:Um in Python ein iterierbares Objekt zu implementieren, müssen Sie lediglich eine Methode angeben __iter__() das ein Objekt zurückgibt, das eine Methode mit dem Namen hat next().Das ist alles dazu:Keine Schnittstellenimplementierung (so etwas gibt es nicht).Keine Unterklassen.Ich rede einfach wie eine Ente / ein Iterator.

BEARBEITEN: Dieser Beitrag wurde positiv bewertet, während ich alles umgeschrieben habe.Tut mir leid, das werde ich nie wieder tun.Der ursprüngliche Inhalt beinhaltete den Rat, so viele Sprachen wie möglich zu lernen und sich keine Gedanken darüber zu machen, was die Sprachärzte über eine Sprache denken/sagen.

Das war tatsächlich ein Abstract-Podcast!
Aber ich verstehe, worauf sie hinaus wollen – Ruby Sparkle hat sie einfach umgehauen.Mit Ruby können Sie Dinge tun, an die C-basierte und Java-Programmierer nicht einmal denken würden + Kombinationen dieser Dinge ermöglichen Ihnen ungeahnte Möglichkeiten.Hinzufügen neuer Methoden zu einer integrierten String-Klasse nach Lust und Laune, Weitergeben unbenannter Codeblöcke zur Ausführung durch andere, Mixins ...Konventionelle Leute sind es nicht gewohnt, dass sich Objekte zu weit von der Klassenvorlage entfernen.Es ist sicher eine ganz neue Welt da draußen.

Was die C#-Leute betrifft, die nicht OO genug sind ...nimm es dir nicht zu Herzen..Nehmen Sie es einfach als den Stoff, den Sie sagen, wenn Ihnen die Worte fehlen.Ruby macht das bei den meisten Menschen.
Wenn ich den Menschen im laufenden Jahrzehnt eine Sprache zum Erlernen empfehlen müsste.es wäre Ruby.Ich bin froh, dass ich es getan habe.Obwohl einige Leute Python behaupten könnten.Aber es entspricht meiner Meinung..Mann!:D

Ich glaube nicht, dass es hier speziell um das Ententippen geht.C# unterstützt beispielsweise bereits eingeschränktes Duck-Typing – ein Beispiel wäre, dass Sie foreach on verwenden können beliebig Klasse, die MoveNext und Current implementiert.

Das Konzept des Duck-Typing ist mit statisch typisierten Sprachen wie Java und C# kompatibel und stellt im Grunde eine Erweiterung der Reflexion dar.

Dies ist tatsächlich der Fall zwischen statischer und dynamischer Eingabe.Beides ist richtig – OO, sofern es so etwas gibt.Außerhalb der Wissenschaft lohnt es sich wirklich nicht, darüber zu diskutieren.

Müllcode kann in beide geschrieben werden.In beiden lässt sich großartiger Code schreiben.Es gibt absolut nichts Funktionales, was ein Modell kann, was das andere nicht kann.

Der eigentliche Unterschied liegt in der Art der durchgeführten Codierung.Statische Typen schränken die Freiheit ein, haben aber den Vorteil, dass jeder weiß, womit er es zu tun hat.Die Möglichkeit, Instanzen im Handumdrehen zu ändern, ist sehr leistungsfähig, aber der Preis besteht darin, dass es schwierig wird, zu wissen, womit man es zu tun hat.

Beispielsweise ist Intellisense für Java oder C# einfach – die IDE kann schnell eine Dropdown-Liste mit Möglichkeiten erstellen.Für Javascript oder Ruby wird dies viel schwieriger.

Für bestimmte Dinge, zum Beispiel die Erstellung einer API, mit der jemand anderes programmieren kann, bietet die statische Typisierung einen echten Vorteil.Bei anderen, beispielsweise bei der schnellen Produktion von Prototypen, liegt der Vorteil in der Dynamik.

Es lohnt sich, beide Fähigkeiten in Ihrem Werkzeugkasten zu verstehen, aber bei weitem nicht so wichtig wie das Verständnis derjenigen, die Sie bereits in der Tiefe verwenden.

Objektorientiert ist ein Konzept.Dieses Konzept basiert auf bestimmten Ideen.Die technischen Namen dieser Ideen (eigentlich eher Prinzipien, die sich im Laufe der Zeit entwickelt haben und nicht von der ersten Stunde an vorhanden waren) wurden oben bereits genannt, ich werde sie nicht wiederholen.Ich erkläre das lieber so einfach und untechnisch wie möglich.

Die Idee der OO-Programmierung ist, dass es Objekte gibt.Objekte sind kleine unabhängige Einheiten.Diese Entitäten können über eingebettete Informationen verfügen oder auch nicht.Wenn sie über solche Informationen verfügen, kann nur die Entität selbst darauf zugreifen oder sie ändern.Die Entitäten kommunizieren miteinander, indem sie untereinander Nachrichten senden.Vergleichen Sie dies mit Menschen.Menschen sind unabhängige Wesen, in deren Gehirn interne Daten gespeichert sind und die durch Kommunikation miteinander interagieren (z. B.miteinander sprechen).Wenn Sie Wissen aus dem Gehirn einer anderen Person benötigen, können Sie nicht direkt darauf zugreifen. Sie müssen ihm eine Frage stellen, und er kann Ihnen darauf antworten und Ihnen sagen, was Sie wissen wollten.

Und das ist es im Grunde.Das ist die eigentliche Idee hinter der OO-Programmierung.Schreiben Sie diese Entitäten, definieren Sie die Kommunikation zwischen ihnen und lassen Sie sie miteinander interagieren, um eine Anwendung zu bilden.Dieses Konzept ist an keine Sprache gebunden.Es ist nur ein Konzept und wenn Sie Ihren Code in C#, Java oder Ruby schreiben, ist das nicht wichtig.Mit etwas mehr Arbeit lässt sich dieses Konzept sogar in reinem C umsetzen, obwohl es sich um eine funktionale Sprache handelt, die aber alles bietet, was man für das Konzept braucht.

Mittlerweile haben verschiedene Sprachen dieses Konzept der OO-Programmierung übernommen, und natürlich sind die Konzepte nicht immer gleich.Einige Sprachen erlauben beispielsweise, was andere Sprachen verbieten.Eines der beteiligten Konzepte ist das Konzept der Klassen.Einige Sprachen haben Klassen, andere nicht.Eine Klasse ist eine Blaupause dafür, wie ein Objekt aussieht.Es definiert die interne Datenspeicherung eines Objekts, es definiert die Nachrichten, die ein Objekt verstehen kann und ob es eine Vererbung gibt (was der Fall ist). nicht erforderlich für OO-Programmierung!), definiert Klassen auch, von welcher anderen Klasse (oder Klassen, wenn Mehrfachvererbung erlaubt ist) diese Klasse erbt (und welche Eigenschaften, wenn selektive Vererbung existiert).Sobald Sie einen solchen Bauplan erstellt haben, können Sie nun eine unbegrenzte Anzahl von Objekten generieren, die nach diesem Bauplan erstellt wurden.

Es gibt jedoch OO-Sprachen, die keine Klassen haben.Wie werden dann Objekte gebaut?Na ja, normalerweise dynamisch.Z.B.Sie können ein neues leeres Objekt erstellen und ihm dann dynamisch interne Strukturen wie Instanzvariablen oder Methoden (Nachrichten) hinzufügen.Oder Sie duplizieren ein bereits vorhandenes Objekt mit allen seinen Eigenschaften und ändern es anschließend.Oder möglicherweise zwei Objekte zu einem neuen zusammenführen.Im Gegensatz zu klassenbasierten Sprachen sind diese Sprachen sehr dynamisch, da Sie Objekte während der Laufzeit dynamisch generieren können, und zwar auf eine Weise, an die nicht einmal der Entwickler gedacht hat, als er mit dem Schreiben des Codes begann.

Normalerweise hat diese Dynamik einen Preis:Je dynamischer eine Sprache ist, desto mehr Speicher (RAM)-Objekte werden verschwendet und desto langsamer wird alles, da auch der Programmfluss äußerst dynamisch ist und es für einen Compiler schwierig ist, effektiven Code zu generieren, wenn er keine Möglichkeit hat, den Code- oder Datenfluss vorherzusagen.JIT-Compiler können einige Teile davon während der Laufzeit optimieren, sobald sie den Programmablauf kennen. Da diese Sprachen jedoch so dynamisch sind, kann sich der Programmablauf jederzeit ändern, was den JIT dazu zwingt, alle Kompilierungsergebnisse zu verwerfen und denselben Code neu zu kompilieren wieder und wieder.

Dies ist jedoch ein winziges Implementierungsdetail – es hat nichts mit dem grundlegenden OO-Prinzip zu tun.Es wird nirgendwo gesagt, dass Objekte dynamisch sein oder zur Laufzeit veränderbar sein müssen.Die Wikipedia sagt es ziemlich gut:

Programmierungstechniken können Merkmale wie Informationsverschluss, Datenabstraktion, Kapselung, Modularität, Polymorphismus und Vererbung umfassen.

http://en.wikipedia.org/wiki/Objektorientierte_Programmierung

Sie Mai oder sie nicht dürfen.Das ist alles nicht zwingend.Zwingend ist nur das Vorhandensein von Objekten und dass diese über Möglichkeiten verfügen müssen, miteinander zu interagieren (ansonsten wären Objekte ziemlich nutzlos, wenn sie nicht miteinander interagieren können).

Du hast gefragt:„Kann mir jemand ein Beispiel für eine wunderbare Sache zeigen, die ich mit Ruby machen könnte, die ich mit C# nicht machen kann und die diesen anderen Oop-Ansatz veranschaulicht?“

Ein gutes Beispiel ist Active Record, das in Schienen integrierte ORM.Die Modellklassen werden zur Laufzeit dynamisch basierend auf dem Datenbankschema erstellt.

Das liegt wahrscheinlich daran, was diese Leute bei anderen in C# und Java sehen, im Gegensatz dazu, dass C# und Java OOP unterstützen.Die meisten Sprachen können in verschiedenen Programmierparadigmen verwendet werden.Sie können beispielsweise prozeduralen Code in C# und Schema schreiben und in Java eine funktionale Programmierung durchführen.Es kommt mehr darauf an, was Sie tun möchten und was die Sprache unterstützt.

Ich werde es versuchen.

Python und Ruby sind Ententypisiert.Um wartbaren Code in diesen Sprachen zu generieren, müssen Sie praktisch eine testgetriebene Entwicklung verwenden.Daher ist es für einen Entwickler sehr wichtig, Abhängigkeiten einfach in seinen Code einzufügen, ohne ein riesiges unterstützendes Framework erstellen zu müssen.

Eine erfolgreiche Abhängigkeitsinjektion hängt von einem ziemlich guten Objektmodell ab.Die beiden sind sozusagen zwei Seiten derselben Medaille.Wenn Sie wirklich wissen, wie man OOP verwendet, sollten Sie standardmäßig Designs erstellen, bei denen Abhängigkeiten einfach eingefügt werden können.

Da die Abhängigkeitsinjektion in dynamisch typisierten Sprachen einfacher ist, haben die Ruby/Python-Entwickler das Gefühl, dass ihre Sprache die Lehren von OO viel besser versteht als andere statisch typisierte Gegenstücke.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top