Unveränderlicher Gegenstand

In der objektorientierten und funktionellen Programmierung ist ein unveränderlicher Gegenstand ein Gegenstand, dessen Staat nicht modifiziert werden kann, nachdem es geschaffen wird. Das ist im Gegensatz zu einem veränderlichen Gegenstand, der modifiziert werden kann, nachdem er geschaffen wird. In einigen Fällen wird ein Gegenstand unveränderlich betrachtet, selbst wenn sich einige innerlich verwendete Attribute ändern, aber der Staat des Gegenstands scheint, aus einem Außengesichtspunkt unveränderlich zu sein. Zum Beispiel konnte ein Gegenstand, der memoization verwendet, um die Ergebnisse der teuren Berechnung zu verstecken, noch als ein unveränderlicher Gegenstand betrachtet werden.

Unveränderliche Gegenstände sind häufig nützlich, weil sie von Natur aus vor dem Faden sicher sind. Andere Vorteile sind, dass sie einfacher sind, zu verstehen und vernünftig zu urteilen über und höhere Sicherheit anzubieten, als veränderliche Gegenstände.

Kleine unveränderliche Gegenstände können effizient leicht kopiert werden, aber größere unveränderliche Gegenstände verlangen, dass mehr komplizierte beharrliche Datenstruktur-Algorithmen effizient kopiert werden. Veränderliche Gegenstände werden manchmal statt unveränderlicher Gegenstände aus Leistungsgründen verwendet.

Hintergrund

In der befehlenden Programmierung, wie man bekannt, unterscheiden Werte, die in Programm-Variablen gehalten sind, deren sich Inhalt nie ändert, als Konstanten, sie von Variablen, die während der Ausführung verändert werden konnten. Beispiele könnten Umwandlungsfaktoren von Kilogramm-Gewichten bis Pfunde oder den Wert von Pi zu mehreren dezimalen Plätzen einschließen.

Auf den meisten objektorientierten Sprachen können Gegenstände auf das Verwenden von Verweisungen verwiesen werden. Einige Beispiele solcher Sprachen sind Java, C ++, C#, VB.NET, und viele scripting Sprachen, wie Pythonschlange und Ruby. In diesem Fall ist es von Bedeutung, ob sich der Staat eines Gegenstands ändern kann, wenn Gegenstände über Verweisungen geteilt werden.

Wenn, wie man bekannt, ein Gegenstand unveränderlich ist, kann er einfach durch das Bilden einer Kopie einer Verweisung darauf kopiert werden, anstatt den kompletten Gegenstand zu kopieren. Weil eine Verweisung (normalerweise nur die Größe eines Zeigestocks) gewöhnlich viel kleiner ist als der Gegenstand selbst, läuft das auf Speicherersparnisse und eine Zunahme in der Ausführungsgeschwindigkeit hinaus.

Die Bezugskopieren-Technik ist viel schwieriger, für veränderliche Gegenstände zu verwenden, weil, wenn ein Benutzer einer Verweisung auf einen veränderlichen Gegenstand sie ändert, alle anderen Benutzer dieser Verweisung die Änderung sehen werden. Wenn das nicht die beabsichtigte Wirkung ist, kann es schwierig sein, die anderen Benutzer zu benachrichtigen, um sie richtig antworten zu lassen. In diesen Situationen ist Defensive, die vom kompletten Gegenstand aber nicht der Verweisung kopiert, gewöhnlich eine leichte, aber kostspielige Lösung. Das Beobachter-Muster ist eine alternative Technik, um Änderungen zu veränderlichen Gegenständen zu behandeln.

Unveränderliche Gegenstände können in Mehrgewindeanwendungen nützlich sein. Vielfache Fäden können Daten folgen, die durch unveränderliche Gegenstände ohne Sorge der Daten vertreten sind, die durch andere Fäden ändern werden. Wie man deshalb betrachtet, sind unveränderliche Gegenstände vor dem Faden sicherer als veränderliche Gegenstände.

Die Praxis, immer Verweisungen im Platz von Kopien von gleichen Gegenständen zu verwenden, ist als das Internieren bekannt. Wenn das Internieren verwendet wird, werden zwei Gegenstände gleich betrachtet, wenn, und nur wenn ihre Verweisungen, normalerweise vertreten als ganze Zahlen, gleich sind. Einige Sprachen tun das automatisch: zum Beispiel, Pythonschlange automatisch Internierte kurze Schnuren. Wenn, wie man versichert, der Algorithmus, der das Internieren durchführt, so in jedem Fall tut, dass es möglich ist, dann wird das Vergleichen von Gegenständen für die Gleichheit auf das Vergleichen ihrer Zeigestöcke, eines wesentlichen Gewinns in der Geschwindigkeit bei den meisten Anwendungen reduziert. (Selbst wenn, wie man versichert, der Algorithmus nicht umfassend ist, dort noch besteht die Möglichkeit einer schnellen Pfad-Fall-Verbesserung, wenn die Gegenstände gleich sind und dieselbe Verweisung verwenden.) Das Internieren ist allgemein nur für unveränderliche Gegenstände nützlich.

Manchmal spricht man bestimmter Felder eines Gegenstands, der unveränderlich ist. Das bedeutet, dass es keine Weise gibt, jene Teile des Gegenstand-Staates zu ändern, wenn auch andere Teile des Gegenstands veränderlich sein können. Wenn alle Felder dann unveränderlich sind, ist der Gegenstand unveränderlich. Dieser könnte zum Beispiel helfen, bestimmten invariants über bestimmte Daten im Gegenstand ausführlich geltend zu machen, der dasselbe durch die Lebenszeit des Gegenstands bleibt. Auf einigen Sprachen wird das mit einem Schlüsselwort getan (z.B in C ++, in Java), der das Feld benennt, unveränderlich zu sein. Auf einigen Sprachen wird es umgekehrt: In OCaml sind Felder eines Gegenstands oder Aufzeichnung standardmäßig unveränderlich, und müssen ausführlich gekennzeichnet werden mit, veränderlich zu sein.

Durchführung

Unveränderlichkeit deutet nicht an, dass der Gegenstand, wie versorgt, im Gedächtnis des Computers unschreibbar ist. Eher ist Unveränderlichkeit eine Übersetzungszeit-Konstruktion, die anzeigt, was ein Programmierer durch die normale Schnittstelle des Gegenstands nicht notwendigerweise tun kann, was sie (zum Beispiel absolut tun können, indem sie das Typ-System überlisten oder const Genauigkeit in C oder C ++ verletzen).

Scala

In Scala kann jede Variable als veränderlich oder unveränderlich definiert werden: In der Behauptung kann man verwenden (schätzen) für unveränderliche Gegenstände und (Variable) für veränderliche.

Zum Beispiel, der folgende Codeschnipsel:

val maxValue = 100

var currentValue = 1

</Quelle>

definiert eine unveränderliche Entität (der Typ der ganzen Zahl wird während der Übersetzung abgeleitet), und eine veränderliche genannte Entität.

Standardmäßig sind Sammlungsklassen solcher als und unveränderlich, so geben Aktualisierungsmethoden ein neues Beispiel zurück, anstatt ein vorhandenes zu verändern. Während das ineffizient klingen kann, bedeuten die Durchführung dieser Klassen und ihre Garantien der Unveränderlichkeit, dass das neue Beispiel vorhandene Knoten wiederverwenden kann, der, besonders im Fall vom Schaffen von Kopien, sehr effizient ist.

Java

Ein klassisches Beispiel eines unveränderlichen Gegenstands ist ein Beispiel der javanischen Klasse.

Spannen Sie s = "Abc";

s.toLowerCase ;

</Quelle>

Die Methode wird die Daten "Abc" nicht ändern, das enthält. Statt dessen wird ein neuer Schnur-Gegenstand realisiert und die Daten "Alphabet" während seines Aufbaus gegeben. Eine Verweisung auf diesen Schnur-Gegenstand wird durch die Methode zurückgegeben. Um die Schnur die Daten "Alphabet" enthalten zu lassen, ist eine verschiedene Annäherung erforderlich.

s = s.toLowerCase ;

</Quelle>

Jetzt bringt die Schnur in einem neuen Schnur-Gegenstand Verweise an, der "Alphabet" enthält. Es gibt nichts in der Syntax der Behauptung der Klassenschnur, die es als unveränderlich geltend macht; eher betrifft keine der Schnur-Klassenmethoden jemals die Daten, die ein Schnur-Gegenstand enthält, so es unveränderlich machend.

Standardmäßig sind Felder und lokale Variablen veränderlich. Sie können das unveränderliche Verwenden des Schlüsselwortes gemacht werden.

interne Nummer i = 42;

i = 43;//, OK

,

endgültige interne Nummer j = 42;

j = 43;//kompiliert </Quelle> nicht

C ++

In C ++ würde eine const-richtige Durchführung dessen dem Benutzer erlauben, neue Beispiele der Klasse entweder als (unveränderlich) oder als veränderlich, wie gewünscht, durch die Versorgung zwei verschiedener Versionen der Methode zu erklären. (Bemerken Sie, dass in C ++ es nicht notwendig - und tatsächlich unmöglich ist - einem Spezialkonstrukteur für Beispiele zur Verfügung zu stellen.)

Schablone

Klassenkarren {\

privat:

std:: Vektor

Publikum:

Karren (const std:: Vektor

std:: Vektor

const std:: Vektor

int Summe const {/* gibt Summe der Preise */}\zurück

};

</Quelle>

Bemerken Sie, dass, wenn es ein Feld gab, das ein Zeigestock oder Verweisung auf einen anderen Gegenstand dann ist, es noch möglich sein könnte sich zu ändern, hat der Gegenstand zu durch solch einen Zeigestock oder Verweisung innerhalb einer const Methode hingewiesen, ohne Const-Genauigkeit zu verletzen. Es kann behauptet werden, dass in solch einem Fall der Gegenstand nicht wirklich unveränderlich ist.

C ++ stellt auch Auszug (im Vergleich mit bitwise) Unveränderlichkeit über das Schlüsselwort zur Verfügung, das einer Mitglied-Variable erlaubt, aus einer Methode geändert zu werden.

SchabloneKlassenkarren {\ privat: std:: Vektor

veränderliche interne Nummer costInCents;

auf veränderlichen bool belaufen;

Publikum: Karren (const std:: Vektor const std:: Vektor

int Summe const {\

wenn (! belaufen) {\

costInCents = 0;

für (std:: Vektor

costInCents + = itor-> costInCents ;

belaufen = wahr;

}\

geben Sie costInCents zurück;

}\

};</Quelle>

Perl

In Perl, eine unveränderliche Klasse schaffend, verlangt zwei Schritte: Erstens kann das Schaffen von Zugriffsberechtigten (entweder automatisch oder manuell), die Modifizierung von Gegenstand-Attributen, und zweitens verhindern, direkte Modifizierung der Beispiel-Daten von Beispielen dieser Klasse verhindernd (wird das gewöhnlich in einer Kuddelmuddel-Verweisung versorgt, und mit dem Kuddelmuddel geschlossen werden:: Die Lock_hash-Funktion von Util):

unveränderliches Paket;

verwenden Sie streng;

verwenden Sie Warnungen;

verwenden Sie Basis qw (Klasse:: Zugriffsberechtigter);

  1. schaffen Sie Read-Only-Zugriffsberechtigte

-> mk_ro_accessors (qw (Wert));

Gebrauch-Kuddelmuddel:: Util 'lock_hash';

U-Boot neuer {\

mein $class = Verschiebung;

geben Sie $class wenn bezüglich (des $class) zurück;

sterben Sie "Argumente für den neuen muss Schlüssel => sein schätzen pairs\n"

wenn (_ % 2 == 0);

mein %defaults = (

schätzen Sie => 'Daten',

);

mein $obj = {\

%defaults,

_,

};

segnen Sie $obj, $class;

# verhindern Modifizierung der Gegenstand-Daten

Lock_hash-%-$obj;

}\

1;

</Quelle>

Oder, mit einem manuell geschriebenen Konstrukteur:

unveränderliches Paket;verwenden Sie streng;verwenden Sie Warnungen;Gebrauch-Kuddelmuddel:: Util 'lock_hash';U-Boot neuer {\ mein $class = Verschiebung; geben Sie $class wenn bezüglich (des $class) zurück; sterben Sie "Argumente für den neuen muss Schlüssel => sein schätzen pairs\n" wenn (_ % 2 == 0); mein %defaults = ( schätzen Sie => 'Daten', ); mein $obj = {\ %defaults, _, }; segnen Sie $obj, $class; # verhindern Modifizierung der Gegenstand-Daten Lock_hash-%-$obj;}\
  1. Read-Only-Zugriffsberechtigter

U-Boot-Wert {\

mein $self = Verschiebung;

wenn (mein $new_value = Verschiebung) {\

# versuchend, einen neuen Wert zu setzen

sterben Sie "Dieser Gegenstand kann nicht modified\n sein";

} sonst {\

kehren Sie zurück $self-> {schätzen }\

}\

}\1;</Quelle>

Pythonschlange

In der Pythonschlange sind einige eingebaute Typen (Zahlen, Schnuren, Tupel, frozensets) unveränderlich, aber kundenspezifische Klassen sind allgemein veränderlich. Um Unveränderlichkeit in einer Klasse vorzutäuschen, sollte man Attribut-Einstellung und Auswischen überreiten, um Ausnahmen zu erheben:

Klasse Unveränderlich (Gegenstand):

" ""Eine unveränderliche Klasse mit einem einzelnen Attribut 'Wert'. """

def __ setattr __ (selbst, *args):

erziehen Sie TypeError ("kann unveränderliches Beispiel" nicht modifizieren)

__ delattr __ = __ setattr __

def __ init __ (selbst, Wert):

# können wir self.value = Wert nicht mehr verwenden, um die Beispiel-Daten zu versorgen

#, so müssen wir die Superklasse ausführlich nennen

super (Unveränderlich, selbst). __ setattr __ ('Wert', Wert)

</Quelle>

Schläger

Schläger weicht wesentlich von anderen Schema-Durchführungen durch das Bilden seines Kernpaar-Typs ab ("lernt Zellen") unveränderlich. Statt dessen stellt es einen parallelen veränderlichen Paar-Typ, über usw. zur Verfügung. Außerdem werden viele unveränderliche Typen, zum Beispiel, unveränderliche Schnuren und Vektoren unterstützt, und diese werden umfassend verwendet. Neue structs sind standardmäßig unveränderlich, wenn ein Feld veränderlich, oder der ganze struct nicht spezifisch erklärt wird:

(struct foo1 (x y)); alle Felder unveränderlicher

(struct foo2 (x [y #:mutable])); ein veränderliches Feld

(struct foo3 (x y) #:mutable); alle Felder veränderlicher

</Quelle>

Die Sprache unterstützt auch unveränderliche Hash-Tabellen, durchgeführt funktionell, und unveränderliche Wörterbücher.

Ada

In Ada wird jeder Gegenstand jede Variable erklärt (d. h. veränderlich; normalerweise der implizite Verzug), oder (d. h. unveränderlich) über das Schlüsselwort.

Typ Some_type ist neue Ganze Zahl; - konnte irgendetwas mehr komplizierter sein

x: unveränderlicher Some_type: = 1; - unveränderlicher

y: Some_type; - veränderlicher

</Quelle>

Unterprogramm-Rahmen sind in in der Weise unveränderlich, und in in und Weisen veränderlich.

Verfahren Do_it (a: in der Ganzen Zahl; b: in der Ganzen Zahl; c: Ganze Zahl) ist

beginnen Sie

- unveränderlichen zu sein

b: = b + a;

c: = a;

Ende Do_it;

</Quelle>

Copy-write

Eine Technik, die die Vorteile von veränderlichen und unveränderlichen Gegenständen vermischt, und direkt in fast der ganzen modernen Hardware unterstützt wird, ist copy-write (KUH). Mit dieser Technik, wenn ein Benutzer das System bittet, einen Gegenstand zu kopieren, wird es stattdessen eine neue Verweisung bloß schaffen, die noch zu demselben Gegenstand hinweist. Sobald ein Benutzer den Gegenstand durch eine besondere Verweisung modifiziert, macht das System eine echte Kopie und veranlasst die Verweisung, sich auf die neue Kopie zu beziehen. Die anderen Benutzer sind ungekünstelt, weil sie sich noch auf den ursprünglichen Gegenstand beziehen. Deshalb, unter der KUH, scheinen alle Benutzer, eine veränderliche Version ihrer Gegenstände zu haben, obwohl im Fall, dass Benutzer ihre Gegenstände nicht modifizieren, die Platzersparnis und Geschwindigkeitsvorteile von unveränderlichen Gegenständen bewahrt werden. Copy-write ist in virtuellen Speichersystemen populär, weil er ihnen erlaubt, Speicherraum noch richtig das Berühren von irgendetwas zu sparen, was ein Anwendungsprogramm tun könnte.

Gebrauch

Schnuren und andere konkrete Gegenstände werden normalerweise als unveränderliche Gegenstände ausgedrückt, Lesbarkeit und Laufzeitleistungsfähigkeit in der objektorientierten Programmierung zu verbessern. In der Pythonschlange, Java und dem.NET Fachwerk, sind Schnuren unveränderliche Gegenstände. Sowohl Java als auch das.NET Fachwerk haben veränderliche Versionen der Schnur. In Java sind diese und (veränderliche Versionen Javas), und in.NET ist das (veränderliche Version von.Net). Pythonschlange 3 hat eine veränderliche Schnur (Bytes) Variante, genannt

.http://docs.python.org/release/3.0/library/functions.html#bytearray

Zusätzlich sind alle primitiven Streifband-Klassen in Java unveränderlich.

Die Erzwingung des Musters kann durch das Verwenden von spezialisierten Bearbeitern überprüft werden (sieh zum Beispiel http://pec.dev.java.net/), und es gibt einen Vorschlag, unveränderliche Typen nach Java hinzuzufügen.

Ähnliche Muster sind die Unveränderliche Schnittstelle und das Unveränderliche Streifband.

Auf reinen funktionellen Programmiersprachen ist es nicht möglich, veränderliche Gegenstände zu schaffen, so sind alle Gegenstände unveränderlich.

Siehe auch

  • Clojure
  • Haskell
  • Erlang
  • Tcl
  • Scala
  • Methode von Mutator

Dieser Artikel enthält ein Material aus dem Perl Designmuster-Buch

Links


Source is a modification of the Wikipedia article Immutable object, licensed under CC-BY-SA. Full list of contributors here.
Dollis Hügel-Tube-Station / Premierminister Wiki
Impressum & Datenschutz