Ich komme aus einem C ++ - Umfeld und habe in meinem aktuellen Job alles mit C # zu tun. Ich habe gerade eine Menge Fragen und Antworten darüber gelesen, was der Unterschied zwischen öffentlichen Feldern und Eigenschaften und all dem Hin und Her in Variationen und Inkarnationen davon ist Grundfrage (zB dieser SO-Beitrag und alle damit verbundenen verknüpften Fragen ). All diese Fragen werden im Hinblick auf praktische Unterschiede behandelt, die die Existenz eines Immobiliensystems für selbstverständlich halten, aber ich denke, es wäre gut, dieses Thema im Hinblick auf das zu betrachten, was die Designer aller Sprachen, die sich entschieden haben, Immobilien im ersten zu unterstützen Ort haben nachgedacht (siehe die Liste im Wikipedia-Artikel hier). Wie hat sich OOP von C ++ / Java zu dem entwickelt, was der Wikipedia-Artikel interessanterweise als Mittelweg zwischen Methoden und Mitgliedsdaten identifiziert:
"Das heißt, Eigenschaften liegen zwischen Elementcode (Methoden) und Elementdaten (Instanzvariablen) der Klasse, und Eigenschaften bieten eine höhere Kapselungsstufe als öffentliche Felder."
MSDN fügt weiteren Hintergrund hinzu:
"Obwohl Eigenschaften Methoden technisch sehr ähnlich sind, unterscheiden sie sich in ihren Verwendungsszenarien erheblich. Sie sollten als intelligente Felder angesehen werden. Sie haben die aufrufende Syntax von Feldern und die Flexibilität von Methoden."
Ich würde gerne wissen, wie es dazu kam, dass sich diese mittlere Kapselungsstufe für die Programmierung im Allgemeinen als nützlich erwies. Ich gehe davon aus, dass dieses Konzept bei der ersten Inkarnation von Programmiersprachen, die das OOP-Paradigma ausdrückten, nicht vorhanden war.
BMI = bob.weight/sq(bob.height)
liest sich besser ohne()
IMO.Antworten:
Alles dreht sich um die Kapselung und das Prinzip des einheitlichen Zugriffs.
Ein Objekt sollte in der Lage sein, auf eine Nachricht zu antworten, indem es entweder vorhandene Daten zurückgibt oder eine Methode ausführt, aber der Absender sollte nicht erkennen können, welche welche ist. Oder wenn Sie dies von der Seite des Absenders aus betrachten: Der Absender sollte in der Lage sein, auf vorhandene Daten zuzugreifen oder eine Methode über eine einheitliche Schnittstelle auszuführen.
Es gibt verschiedene Möglichkeiten, dies zu erreichen:
Daten insgesamt loswerden, nur Methoden haben (Newspeak macht das)
Methoden insgesamt loswerden, nur Daten haben (Selbst tut dies, "Methoden" sind nur
Method
Objekte, die Instanzvariablen zugewiesen sind, Instanzvariablen werden mit virtuellem Versand nachgeschlagen)Nehmen Sie keine syntaktische oder semantische Unterscheidung zwischen Methoden und Daten vor (Scala führt dies aus. Der Zugriff auf ein Feld ist syntaktisch nicht vom Aufrufen einer Methode ohne Argumentliste (
foo.bar
) zu unterscheiden. Die Zuweisung zu einem Feld ist syntaktisch nicht vom Aufrufen einer speziell benannten Methode (foo.bar = baz
) zu unterscheiden B. dasfoo.bar_=(baz)
Aufrufen einer benannten Methodefoo_=
und schreibgeschützte Werte können von einer Methode ohne Parameterliste überschrieben oder implementiert werden (dhval foo
) in einer Oberklasse kannabstract
val
in einer Unterklasse mit einer Methode überschrieben (oder implementiertdef foo
) werden.Java folgt jedoch nicht dem Prinzip des einheitlichen Zugriffs. In Java kann zwischen dem Zugriff auf Daten und dem Ausführen einer Methode unterschieden werden.
foo.bar
ist anders alsfoo.bar()
. Der Grund dafür ist, dass Felder und Methoden semantisch und syntaktisch unterschiedlich sind.C # versucht, dies zu beheben, indem der Sprache Eigenschaften hinzugefügt werden, im Grunde Methoden, die wie Felder aussehen. Methodenaufrufe sehen jedoch immer noch anders aus als Feld- und Eigenschaftszugriffe. Felder und Eigenschaften haben jetzt einheitlichen Zugriff, Methoden jedoch immer noch nicht.
Dies behebt das Problem also nicht wirklich: Sie können nicht zwei verschiedene Möglichkeiten für den Zugriff auf Dinge beheben, indem Sie eine dritte Möglichkeit für den Zugriff auf Dinge hinzufügen! Selbst wenn dieser dritte Weg wie einer der beiden anderen Wege aussieht, haben Sie (mindestens) zwei verschiedene Wege. Sie können das Problem nur beheben, indem Sie entweder alle verschiedenen Möglichkeiten außer einer oder die Unterschiede beseitigen.
Es ist vollkommen in Ordnung, eine Sprache mit Methoden, Eigenschaften und Feldern zu haben, aber alle drei sollten einen einheitlichen Zugriff haben.
quelle
Nun, ich bin nicht 100% sicher, aber ich denke, die Dinge sind wahrscheinlich einfacher als Sie erwarten. Von den OO-Modellierungsschulen der 90er Jahre gab es eine Nachfrage nach Modellierungsklassen mit gekapselten Mitgliedsattributen, und wenn sie in Sprachen wie C ++ oder Java implementiert wurden, führte dies normalerweise zu Code mit vielen Gettern und Setzern, also viel "Rauschen". Code für eine relativ einfache Anforderung. Beachten Sie, dass die meisten (wahrscheinlich alle, die dies nicht überprüft haben) der in Ihrem verlinkten Wikipedia-Artikel aufgeführten Sprachen Ende der 90er Jahre oder später damit begannen, "Eigenschaften" von Objekten einzuführen.
Ich denke, das war der Hauptgrund, warum Sprachdesigner beschlossen, syntaktischen Zucker hinzuzufügen, um dieses Rauschen zu reduzieren. Und obwohl Eigenschaften sicherlich kein "Kern-OO-Konzept" sind, haben sie zumindest etwas mit der Objektorientierung zu tun. Sie zeigen keine "Entwicklung von OOP" (wie in Ihrem Fragentitel angenommen), unterstützen jedoch die OO- Modellierung auf der Ebene der Programmiersprache, um die Implementierung zu vereinfachen.
quelle
Sie haben es rückwärts (irgendwie). Lambda Calculus ist seit Jahrzehnten die wichtigste formale Grundlage für Programmiersprachen. Es hat keine Felder.
Um einen veränderlichen Zustand zu modellieren, müssen Sie zwei Abstraktionen erstellen. Eine stellt das Festlegen eines Status dar und eine andere, die diesen Status abruft (Kapitel 13 in meiner Version von TaPL als Referenz). Klingt bekannt? Aus theoretischer Sicht hat sich OO nicht weiterentwickelt, um dieses Zeug zu haben. OO las Programmiersprachen 101 und machte einen kleinen Schritt nach vorne.
Aus praktischer Sicht gibt es zwei ziemlich klare Motivationen. Sie haben einen C ++ - Hintergrund. Was müsste also passieren, wenn Sie ein öffentliches Feld hätten? Sagen Sie ... den Text in einem Textfeld. Was passiert, wenn Sie Ihr Design so ändern möchten, dass "wann immer sich dieses Textfeld ändert, tun Sie es bla"? Sie können dieses Feld töten, eine oder zwei Funktionen erstellen und diese Logik verkabeln, da Sie Entwicklern nicht vertrauen können, dass sie "UpdateTextbox" selbst aufrufen. Dies ist eine sehr bahnbrechende Änderung an Ihrer API (und leider immer noch eine bahnbrechende Änderung an der Implementierung von Eigenschaften in .NET). Diese Art von Verhalten ist ganz über den Platz in dem Windows - API. Da dies bei Microsoft eine große Sache ist, wollte C # dies wahrscheinlich weniger schmerzhaft machen.
Die andere große Motivation sind Java Beans und ihre Verwandten. Eine Reihe von Frameworks wurden gebaut für Java Reflexion Look zu verwenden
GetX
undSetX
Paare und effektiv wie moderne Eigenschaften zu behandeln. Da es sich jedoch nicht um tatsächliche Sprachkonstrukte handelte, waren diese Frameworks fragil und unfreundlich. Wenn Sie einen Namen tippen würden, würden die Dinge einfach lautlos brechen. Wenn einer umgestaltet wurde, bewegte sich nichts auf der anderen Seite des Grundstücks. Und das ganze Feld / Get / Set-Boilerplate zu machen war ausführlich und mühsam (sogar für Java!). Da C # größtenteils als "Java mit gewonnenen Erkenntnissen" entwickelt wurde, war diese Art von Schmerz eine dieser Lektionen.Das Größte ist jedoch, dass das Immobilienkonzept erfolgreich war. Es ist leicht zu verstehen, es ist einfach zu bedienen. Diese helfen bei der Einführung erheblich, und als Werkzeug haben Programmierer festgestellt, dass Eigenschaften eine Teilmenge von Problemen sauberer lösen als Funktionen oder Felder.
quelle
Insbesondere in .net stammen Eigenschaften aus den alten Visual Basic-Tagen, die nicht so objektorientiert waren, wie wir es heute sehen. Es wurde größtenteils um das damals neue COM-System herum aufgebaut, das oberflächlich alles nicht unbedingt als Klassen behandelte, sondern als Komponenten, die Eigenschaften offenlegen würden, auf die sowohl im Code als auch in grafischen Editoren zugegriffen werden konnte. Als VB und das neu erstellte C # in .net zusammengeführt wurden, erhielt VB eine ganze Reihe von OOP-Funktionen und behielt die Eigenschaften bei, da das Entfernen wie ein Rückschritt wäre - stellen Sie sich vor, das automatische Code-Update-Tool in Visual Studio wäre es gewesen Das Ersetzen aller Ihrer Eigenschaften durch Getter und Setter hat die Kompatibilität mit allen COM-Bibliotheken beeinträchtigt. Es wäre nur logisch, sie insgesamt zu unterstützen.
quelle
Eigenschaften haben nichts mit objektorientierter Programmierung zu tun, da Eigenschaften nur syntaktischer Zucker sind. Eigenschaften sehen oberflächlich wie Felder aus, und in der .net-Welt wird empfohlen, dass sie sich in gewisser Weise wie Felder verhalten, aber in keiner Weise Felder sind. Eigenschaften sind syntaktischer Zucker für eine oder zwei Methoden: eine zum Abrufen eines Werts und eine zum Festlegen eines Werts. Entweder die set-Methode oder die get-Methode können weggelassen werden, aber nicht beide. Möglicherweise ist kein Feld vorhanden, in dem der von der get-Methode zurückgegebene Wert gespeichert ist. Da sie eine Syntax mit Feldern teilen und häufig Felder verwenden, verknüpfen Benutzer Eigenschaften mit Feldern.
Eigenschaften haben Vorteile gegenüber Feldern:
Da Eigenschaften die Abstraktion von Feldern sind und aus syntaktischen Gründen Sprachen wie C # die Feldsyntax für Eigenschaften übernehmen.
quelle
Es geht um Implementierung und Implikation . Die Eigenschaften befanden sich in OOP, bevor C ++ oder Java die Szene betraten (sie befanden sich in Simula mit einer gewissen Rauheit an den Rändern und sind für Smalltalk von grundlegender Bedeutung). Entitäten mit Eigenschaften unterscheiden sich konzeptionell von Werten mit angehängtem Code. Die get & set-Präfixe in einigen Sprachkonventionen dienen nur dazu, das Wasser zu trüben. Sie machen Sie auf den Unterschied zwischen Feldern und Eigenschaften aufmerksam, vorausgesetzt, dass auf Felder direkt zugegriffen werden kann, ohne dass get / set auf eine für die Sprache idiomatische und undichte Weise erfolgt.
Der springende Punkt bei OOP ist, Dinge so zu behandeln, als wären sie Entitäten in der "realen" Welt, nicht nur als Strukturen mit eingemischtem Code. Ein anderer Programmierer sollte sehr, sehr wenig über die Art und Weise wissen müssen, wie ich Dinge implementiert habe, und sollte sich überhaupt nicht darum kümmern, welche der verschiedenen Werte, die sie erhalten und / oder setzen dürfen, real und welche virtuell sind. Wenn Sie auf einen meiner Vektoren stoßen, sollten Sie nicht wissen müssen, ob ich Winkel und Größe oder reale und imaginäre Komponenten innerhalb des Vektorobjekts speichere. Wenn ich die Darstellung in V2.0 meiner Bibliothek ändere, sollte dies keinen Einfluss auf Ihren Code haben (obwohl Sie möglicherweise die coolen neuen Funktionen nutzen möchten). Ebenso gibt es Eigenschaften, die eine Entität haben kann und die von Daten außerhalb der Entität abhängen. aber die sind zweifellos Eigenschaften aus lexikalischer Sicht. Sie fragen die Leute "wie alt sind Sie", nicht "bitte führen Sie die Berechnung durch, die mir Ihr Alter offenbart", obwohl Sie wissen, dass die für dieses "Objekt" verfügbaren Daten das Geburtsdatum (ein privates unveränderliches Mitglied) und das heutige sind Datum (eine öffentliche, automatisch inkrementierende Umwelteigenschaft, abhängig von der Zeitzone, der Sommerzeit und der internationalen Datumsgrenze). Alter ist eine Eigenschaft, keine Methode, obwohl es einige Berechnungen erfordert, um dorthin zu gelangen, und nicht (außer in Spielzeugcomputer-Darstellungen von Dingen mit künstlich begrenzten Lebensdauern) als Feld gespeichert werden kann. obwohl Sie wissen, dass die für dieses "Objekt" verfügbaren Daten das Geburtsdatum (ein privates unveränderliches Mitglied) und das heutige Datum (eine öffentliche, automatisch inkrementierende Umwelteigenschaft, abhängig von der Zeitzone, der Sommerzeit und der internationalen Datumsgrenze) sind ). Alter ist eine Eigenschaft, keine Methode, obwohl es einige Berechnungen erfordert, um dorthin zu gelangen, und nicht (außer in Spielzeugcomputer-Darstellungen von Dingen mit künstlich begrenzten Lebensdauern) als Feld gespeichert werden kann. obwohl Sie wissen, dass die für dieses "Objekt" verfügbaren Daten das Geburtsdatum (ein privates unveränderliches Mitglied) und das heutige Datum (eine öffentliche, automatisch inkrementierende Umwelteigenschaft, abhängig von der Zeitzone, der Sommerzeit und der internationalen Datumsgrenze) sind ). Alter ist eine Eigenschaft, keine Methode, obwohl es einige Berechnungen erfordert, um dorthin zu gelangen, und nicht (außer in Spielzeugcomputer-Darstellungen von Dingen mit künstlich begrenzten Lebensdauern) als Feld gespeichert werden kann.
Anstatt Eigenschaften als das Bastardkind von Feldern und Methoden zu betrachten, ist es weitaus befriedigender, Methoden als eine spezielle Art von Eigenschaft zu betrachten - Dinge, die Ihre Entitäten tun können, anstatt Dinge, die sie sind. Andernfalls handelt es sich nicht konzeptionell um Objekte / Entitäten, sondern um Datensammlungen, an die zufällig Code angehängt ist. Die Implementierungen mögen identisch sein, aber die Implikationen sind unterschiedlich.
Es ist jedoch unnötig zu erwähnen, dass diese Abstraktion mit Kosten verbunden ist. Wenn ein Programmierer, der eine Klasse verwendet, nicht feststellen kann, ob er auf gespeicherte Daten zugreift oder Werte abruft / einstellt, die berechnet werden müssen, gibt es eine Ebene, auf der die Sprache ebenfalls notwendigerweise unsicher ist (und daher möglicherweise unsicher ist) erfordern, dass alles Code erfordert, um zwischen Accessoren / Selektoren und Werten zu wechseln). Es ist konzeptionell nichts Falsches an "Strukturen mit Code" - sie können sicherlich viel effizienter sein -, aber sie lecken überall die Implementierung, und das ist eines der Dinge, die OOP beseitigen soll.
quelle
Absolut nichts. Eigenschaften und OOP haben nichts miteinander zu tun. Eigenschaften sind nichts anderes als syntaktischer Zucker für Funktionsaufrufe und haben daher genau den gleichen OOP-Anhang wie Funktionsaufrufe, dh keine.
Wikipedia ist übrigens völlig falsch. Das in Java angezeigte Muster getMember / setMember bietet genau die gleichen Vor- und Nachteile wie die Eigenschaften in C #. Und Sie können dieses Muster auch in C replizieren, wenn Sie möchten.
Eigenschaften in C # sind nichts anderes als sprachgestützter syntaktischer Zucker.
quelle