Was ist ein Staat, ein veränderlicher Staat und ein unveränderlicher Staat?

32

Dies ist eine Frage für Neulinge, aber ich konnte auf Google keine Antwort finden, die für Neulinge beweiskräftig genug ist.

Was bedeuten die Leute, wenn sie "Zustand" sagen - bei der Programmierung im Allgemeinen und bei der OO-Programmierung im Speziellen?

Auch, was ist veränderlicher und unveränderlicher Zustand - wieder allgemein in der Programmierung und auch spezifisch in OOP?

Aviv Cohn
quelle
4
Das Teilen Ihrer Forschung hilft allen . Sagen Sie uns, was Sie versucht haben und warum es nicht Ihren Bedürfnissen entsprach. Dies zeigt, dass Sie sich die Zeit genommen haben, um sich selbst zu helfen, es erspart uns, offensichtliche Antworten zu wiederholen, und vor allem hilft es Ihnen, eine spezifischere und relevantere Antwort zu erhalten. Siehe auch Wie man fragt
Mücke

Antworten:

46

Sie haben Zustand, wenn Sie einer Identität und einem Zeitpunkt Werte (Zahlen, Zeichenfolgen, komplexe Datenstrukturen) zuordnen.

Beispielsweise stellt die Zahl 10 für sich genommen keinen Zustand dar: Sie ist nur eine genau definierte Zahl und wird immer für sich selbst stehen: die natürliche Zahl 10. In einem anderen Beispiel ist die Zeichenfolge "HELLO" eine Folge von fünf Zeichen und Es wird vollständig durch die darin enthaltenen Zeichen und die Reihenfolge ihres Auftretens beschrieben. In fünf Millionen Jahren wird die Saite "HELLO" immer noch die Saite "HELLO" sein: ein reiner Wert.

Um einen Zustand zu haben, muss man eine Welt betrachten, in der diese reinen Werte mit einer Art von Entitäten verbunden sind, die eine Identität besitzen . Identität ist eine primitive Idee: Sie können zwei Dinge unabhängig von anderen Eigenschaften unterscheiden. Zum Beispiel sind zwei Autos des gleichen Modells, der gleichen Farbe, ... zwei verschiedene Autos.

Wenn Sie diese Dinge mit Identität versehen, können Sie ihnen Eigenschaften zuweisen, die durch reine Werte beschrieben werden. Mein Auto hat zum Beispiel die Eigenschaft, blau zu sein. Sie können diese Tatsache beschreiben, indem Sie das Paar zuordnen

("colour", "blue")

zu meinem Auto. Das Paar ("Farbe", "Blau") ist ein reiner Wert, der den Zustand dieses bestimmten Autos beschreibt.

Staat ist nicht nur mit einer bestimmten Entität verbunden, sondern auch mit einem bestimmten Zeitpunkt. So kann man sagen, dass mein Auto heute Zustand hat

("colour", "blue")

Morgen werde ich es schwarz übermalen lassen und der neue Zustand wird sein

("colour", "black")

Beachten Sie, dass sich der Status einer Entität ändern kann, die Identität sich jedoch nicht per Definition ändert . Nun, solange die Entität existiert, kann ein Auto geschaffen und zerstört werden, aber es behält seine Identität während seines gesamten Lebens. Es macht keinen Sinn, über die Identität von etwas zu sprechen, das noch nicht existiert.

Wenn sich die Werte der Eigenschaften, die an eine bestimmte Entität angehängt sind, im Laufe der Zeit ändern, können Sie davon ausgehen, dass der Status dieser Entität geändert werden kann . Ansonsten sagst du, dass der Staat unveränderlich ist .

Die gebräuchlichste Implementierung besteht darin, den Status einer Entität in einer Art von Variablen (globale Variablen, Objektelementvariablen) zu speichern, dh den aktuellen Snapshot eines Status zu speichern . Der veränderbare Zustand wird dann durch Zuweisung implementiert: Jede Zuweisungsoperation ersetzt den vorherigen Schnappschuss durch einen neuen. Diese Lösung verwendet normalerweise Speicherorte zum Speichern des aktuellen Schnappschusses. Das Überschreiben eines Speicherorts ist ein destruktiver Vorgang, bei dem ein Schnappschuss durch einen neuen ersetzt wird. ( Hier finden Sie einen interessanten Vortrag über diesen ortsorientierten Programmieransatz .)

Eine Alternative besteht darin, die nachfolgenden Zustände (Verlauf) einer Entität als Strom (möglicherweise unendliche Folge) von Werten anzuzeigen , siehe z. B. Kapitel 3 von SICP . In diesem Fall wird jeder Schnappschuss an einem anderen Speicherort gespeichert, und das Programm kann gleichzeitig verschiedene Schnappschüsse untersuchen. Nicht verwendete Schnappschüsse können über den Müll gesammelt werden, wenn sie nicht mehr benötigt werden.

Vor- und Nachteile der beiden Ansätze

  • Ansatz 1 verbraucht weniger Speicher und ermöglicht eine effizientere Erstellung eines neuen Snapshots, da kein Kopieren erforderlich ist.
  • Ansatz 1 überträgt den neuen Status implizit auf alle Teile eines Programms, die einen Verweis darauf enthalten. Ansatz 2 benötigt einen Mechanismus, um einen Snapshot an seine Beobachter zu übertragen, z. B. in Form eines Ereignisses.
  • Ansatz 2 kann dazu beitragen, inkonsistente Statusfehler (z. B. Teilstatusaktualisierungen) zu vermeiden: Durch die Definition einer expliziten Funktion, die einen neuen Status von einem alten erzeugt, ist es einfacher, zwischen Snapshots zu unterscheiden, die zu verschiedenen Zeitpunkten erstellt wurden.
  • Der Ansatz 2 ist modularer, da er es ermöglicht, auf einfache Weise Ansichten über den Zustand zu erstellen, die unabhängig von dem Zustand selbst sind, z. B. unter Verwendung von Funktionen höherer Ordnung wie mapund filter.
Giorgio
quelle
1
Beachten Sie, dass Objekte nicht die einzigen Dinge mit Status sind. Wenn ein Programm (veränderbare) globale Variablen verwendet, hat das Programm selbst den Status. Wenn eine Funktion eine Variable hat, die sich Werte über Funktionsaufrufe hinweg merkt, ist die Funktion ebenfalls statusbehaftet.
Doval
2
@Doval: Sie können sich den globalen Zustand als den Zustand eines globalen Weltobjekts vorstellen. Soweit ich weiß, wird diese Ansicht zB in Ruby verwendet. Eine Funktion, die sich an einen Zustand erinnert, ist mit nur einer Methode isomorph zu einem Objekt. Die übliche Grundidee ist, dass Sie Identitäten oder Orten Werte zuordnen, dh dass bestimmte Dinge Werte enthalten können (möglicherweise veränderliche Werte), aber ihre Identität behalten.
Giorgio
3
Klar, ich stimme grundsätzlich zu. Ich stelle nur sicher, dass Prog versteht, dass Staatlichkeit etwas ist, das OOP nicht ausschließt. Ich denke nicht, dass die Gedankenlinie "Alles ist ein Objekt" ganz natürlich ist.
Doval
@Doval: Sie haben Stateful-Funktionen erwähnt, die Werte über verschiedene Aufrufe hinweg speichern. Ein Beispiel, an das ich denken kann, sind statische lokale Variablen in C. Ein anderes Beispiel sind Abschlüsse (Funktionen, die in ihrem Kontext definierte Variablen erfassen). Closures sind für Objekte etwas dual: Ein Closure ist ein Objekt mit genau einer Methode, während ein Objekt eine Sammlung von Closures ist, die über dieselben Variablen definiert sind. Sie wissen wahrscheinlich alles, aber ich wollte es hier zusammenfassen. Im Allgemeinen können Sie den Status an einem bestimmten Speicherort speichern und mithilfe verschiedener Mechanismen darauf zugreifen, wie Sie bereits betont haben.
Giorgio
11

Zustand ist einfach Information über etwas, das in Erinnerung bleibt.

Stellen Sie sich als einfache Übung zur Objektorientierung eine Klasse als Ausstecher und Cookies als Objekte vor. Mit der Ausstechform (Klasse) können Sie ein Cookie erstellen (ein Objekt instanziieren). Angenommen, eine der Eigenschaften des Kekses ist seine Farbe (die durch Verwendung von Lebensmittelfarben geändert werden kann). Die Farbe dieses Cookies ist Teil seines Zustands, ebenso wie die anderen Eigenschaften.

Der veränderbare Status ist der Status, der geändert werden kann, nachdem Sie das Objekt erstellt haben (Cookie). Der unveränderliche Zustand ist ein Zustand, der nicht geändert werden kann.

Unveränderliche Objekte (für die keiner der Status geändert werden kann) werden wichtig, wenn Sie sich mit der Parallelität befassen, dh wenn mehr als ein Prozessor in Ihrem Computer gleichzeitig mit diesem Objekt arbeiten kann. Unveränderlichkeit garantiert, dass Sie sich darauf verlassen können, dass der Zustand während der gesamten Lebensdauer des Objekts stabil und gültig ist.

Im Allgemeinen wird der Status eines Objekts in "privaten oder Mitgliedsvariablen" gespeichert und über "Eigenschaften" oder Getter / Setter-Methoden aufgerufen.

Robert Harvey
quelle
3
Zum Wohle von Prog ist es auch wichtig, dass sich ein Wert niemals ändert, da es viel einfacher ist, darüber nachzudenken. Es kann in so vielen Funktionen / Methoden verwendet werden, wie Sie möchten, und Sie wissen, dass sie es nicht ändern können. Mit dem veränderlichen Zustand müssen Sie den Verlauf verfolgen, wie dieses Objekt verwendet wurde, um herauszufinden, welchen Wert es jetzt hat . Das ist unnötiger mentaler Aufwand, wenn es das Programm nicht kompliziert, es unveränderlich zu machen.
Doval
Danke für die Antwort. Wenn also in OOP jemand 'state' sagt, bedeutet er normalerweise "Mitgliedsvariablen eines Objekts"? Wenn ja, dann ist "veränderlicher Zustand" eine öffentliche Variable oder häufiger eine private Variable in OOP, die mit Setter-Methoden geändert werden kann - während "unveränderlicher Zustand" einfach eine private Mitgliedsvariable ist?
Aviv Cohn
1
Unveränderlichkeit kann simuliert werden, indem einfach nie mehr in die privaten Mitglieder eines Objekts geschrieben wird, wenn diese erst einmal mit Anfangswerten gefüllt sind. Die Unveränderlichkeit kann mit einer Reihe von Methoden erzwungen werden: Keine Setter-Methode, der Anfangswert muss mithilfe eines Konstruktorparameters festgelegt, in einem funktionalen Stil geschrieben, Konstanten usw. verwendet werden.
Robert Harvey,
1
Ich stelle mir Staat als den Wert eines Eigentums einer Entität vor. "Versendet" ist ein Staat. So ist "Steuersatz". Das Gewicht von etwas ist ein Zustand. Ob Sie gerade wach sind oder schlafen, ist ein Zustand. Die Farbe von etwas ist ein Zustand. Aussagekräftige Informationen zu etwas, die sich in einem Computerspeicher befinden.
Robert Harvey
1
In vielen Sprachen kann die Unveränderlichkeit erzwungen werden, indem Mitgliedsvariablen als "const" oder "final" deklariert werden. Solche Variablen können nur vom Konstruktor initialisiert werden. Gehen Sie nicht davon aus, dass private Variablen unveränderlich sind - sie können weiterhin durch die Member-Funktionen (Methoden) der Klasse geändert werden.
Simon B
7

Ich denke, der Begriff "Zustand" (im Gegensatz zu einem konkreten Zustandstyp wie "Mitgliedsvariable") ist am nützlichsten, wenn eine zustandsbehaftete API mit einer zustandslosen API verglichen wird. Der Versuch, "state" zu definieren, ohne APIs zu erwähnen, ähnelt dem Versuch, "variable" oder "function" zu definieren, ohne Programmiersprachen zu erwähnen. Die meisten der richtigen Antworten sind nur für Personen sinnvoll, die bereits wissen, was die Wörter bedeuten.

Stateful vs Staatenlos

  • Eine statusbehaftete API "merkt" sich, welche Funktionen Sie bisher aufgerufen haben und mit welchen Argumenten. Wenn Sie eine Funktion das nächste Mal aufrufen, werden diese Informationen verwendet. Der Teil "Erinnern" wird oft mit Elementvariablen implementiert, aber das ist nicht der einzige Weg.
  • Eine zustandslose API ist eine API, bei der jeder Funktionsaufruf ausschließlich von den an sie übergebenen Argumenten abhängt und von nichts anderem.

Zum Beispiel ist OpenGL wahrscheinlich die zustandsstärkste API, die mir bekannt ist. Wenn ich es für einen Moment lächerlich stark vereinfachen darf, könnten wir sagen, dass es ungefähr so ​​aussieht:

glSetCurrentVertexBufferArray(vba1);
glSetCurrentVertexBufferObject(vbo1);
glSetCurrentVertexShader(vert1);
glSetCurrentFragmentShader(frag1);
// a dozen other things
glActuallyDrawStuffWithCurrentState(GL_TRIANGLES);

Fast jede Funktion wird nur verwendet, um einen Teil des Zustands zu übergeben, an den sich OpenGL erinnern muss. Am Ende rufen Sie eine antiklimaktisch einfache Funktion auf, um die gesamte Zeichnung durchzuführen.

Eine zustandslose Version von (stark vereinfachtem) OpenGL würde wahrscheinlich ungefähr so ​​aussehen:

glActuallyDrawStuff(vba1, vbo1, vert1, frag1, /* a dozen other things */, GL_TRIANGLES);

Sie werden oft Leute sagen hören, dass APIs mit weniger Status einfacher zu begründen sind. Wenn Sie die Anzahl der Argumente unter Kontrolle halten können, stimme ich dem im Allgemeinen zu.

Veränderlich gegen unveränderlich

Diese Unterscheidung ist meines Wissens nur dann sinnvoll, wenn Sie einen Ausgangszustand angeben können . Zum Beispiel mit C ++ - Konstruktoren:

// immutable state
ImmutableWindow windowA = new ImmutableWindow(600, 400);
windowA = new ImmutableWindow(800, 600); // to change the size, I need a whole new window

// mutable state
MutableWindow windowB = new MutableWindow(600, 400);
windowB.width = 800; // to change the size, I just alter the existing object
windowB.height = 600;

Es ist schwierig, eine Fensterklasse zu implementieren, die sich nicht an die Größe "erinnert". Sie können jedoch entscheiden, ob der Benutzer die Größe eines Fensters nach dem Erstellen ändern kann.

PS In OOP ist es wahr, dass "state" normalerweise "member variables" bedeutet, aber es kann noch viel mehr sein. In C ++ kann eine Methode beispielsweise eine statische Variable haben, und Lambdas können durch Erfassen von Variablen zu Abschlüssen werden. In beiden Fällen bleiben diese Variablen über mehrere Aufrufe der Funktion bestehen und werden daher wahrscheinlich als Status qualifiziert. Lokale Variablen in einer regulären Funktion können auch als Status betrachtet werden, je nachdem, wie sie verwendet werden (die, die ich in main () habe, zählen oft).

Ixrec
quelle
FANTASTISCHE Antwort. Vielen Dank, Sie haben mir wirklich geholfen, das schnell zu verstehen. Wenig wusste ich, ich habe lange damit gearbeitet und wusste nicht, wie es hieß.
the_endian
2

In Laienwörtern

Das Wörterbuch besagt:

ein. Eine Bedingung oder ein Modus des Seins in Bezug auf die Umstände.

  1. state - die Art und Weise, wie etwas in Bezug auf seine Hauptattribute ist;

Der Zustand von etwas ist die Menge von Werten, die seine Attribute zu einem bestimmten Zeitpunkt haben.

In OOP ist der Status eines Objekts eine Momentaufnahme der Werte seiner Attribute zu einem bestimmten Zeitpunkt.

Thing t = new Thing();
t.setColor("blue");
t.setPrice(100)
t.setSize("small");

Der Zustand davon ist, dass seine Farbe blau ist, sein Preis 100 ist und seine Größe klein ist.

Wenn Sie später tun:

t.setColor("red");

Sie haben eines der Attribute geändert, aber Sie haben auch den Status insgesamt geändert, da das Objekt nicht mehr so ​​ist wie es war.

Manchmal werden Klassen so entworfen, dass die Werte ihrer Eigenschaften nach ihrer Erstellung nicht mehr geändert werden können. Alle Werte ihrer Eigenschaften werden entweder an den Konstruktor übergeben oder aus einer Quelle wie einer Datenbank oder einer Datei gelesen. Es gibt jedoch keine Möglichkeit, diese Werte nach diesem Zeitpunkt zu ändern, da es keine "Setter" -Methoden oder andere Methoden gibt Ändern der Werte im Objekt.

Thing t = new Thing("red",100,"small");
t.setColor("blue") -->> ERROR, the programmer didn't provide a setter or any other way to change the properties values after initialization.

Das nennt man einen Zustand, der nicht mutiert werden kann. Alles, was Sie tun können, ist, das Objekt zu zerstören, ein neues zu erstellen und es derselben Referenz oder Variablen zuzuweisen.

Thing t = new Thing("red",100,"small");
t = new Thing("blue",100,"small");
// I had to create a new Thing with another color since this thing is inmutable.
Tulains Córdova
quelle