Als ich versuchte, die ID
Eigenschaft der byValueObj
Instanz zu ändern, erhielt ich einen Fehler, der mir sagte, dass ich der Eigenschaft einer Konstante nicht zuweisen kann, obwohl die Eigenschaft eine Variable ist. Ich kann es jedoch in einer Klasseninstanz tun. Ich weiß irgendwie, dass es etwas mit dem Wert- und Referenzmechanismus zu tun hat. Aber ich habe kein sehr klares und richtiges Verständnis davon. Kann mir jemand das erklären? Danke.
Strukturen in Swift sind Werttypen - und semantisch gesehen Werte (dh 'Instanzen') von Werttypen) sind unveränderlich.
Eine Mutation eines Werttyps, sei es durch direkte Änderung des Werts einer Eigenschaft oder durch Verwendung einer mutating
-Methode, entspricht der Zuweisung eines vollständig neuen -Wertes an die Variable hält es (plus irgendwelche Nebenwirkungen, die die Mutation ausgelöst haben). Daher muss die Variable, die es enthält, ein var
sein. Und diese Semantik wird durch das Verhalten von Eigenschaftenbeobachtern rund um Werttypen, wie
Was das bedeutet ist, dass Sie sich das vorstellen können:
%Vor%wie folgt:
%Vor% Und wie Sie deutlich sehen können - dieser Code ist illegal. Sie können fooCopy
nicht zu foo
zurückgeben, da es sich um eine let
Konstante handelt. Daher können Sie die Eigenschaft eines Werttyps, der als let
deklariert ist, nicht ändern und müssen ihn daher zu einem var
machen.
(Es ist erwähnenswert, dass der Compiler dieses Palaver nicht wirklich durchläuft; es kann die Eigenschaften von Strukturen direkt verändern, was man an der erzeugte SIL . Dies ändert jedoch nicht die Semantik der Werttypen.)
Der Grund, warum Sie eine veränderbare Eigenschaft einer Instanz let
constant class ändern können, liegt an der Tatsache, dass Klassen Referenztypen sind. Eine let
-Konstante sicherzustellen, stellt nur sicher, dass die Referenz gleich bleibt. Das Mutieren ihrer Eigenschaften beeinflusst in keiner Weise Ihre Referenz auf sie - Sie beziehen sich immer noch auf den selben Speicherort im Speicher.
Sie können sich einen Bezugstyp wie einen Wegweiser vorstellen, daher Code wie folgt:
%Vor%Sie können sich die Speicherdarstellung so vorstellen:
%Vor%Und wenn Sie eine Eigenschaft mutieren:
%Vor% Die Referenz ( referenceToFoo
) selbst ist nicht betroffen - Sie zeigen immer noch auf denselben Speicherort im Speicher. Es ist die Eigenschaft der zugrunde liegenden Instanz, die geändert wurde (dh die zugrunde liegende Instanz wurde mutiert):
Nur wenn Sie versuchen, einen neuen Verweis auf referenceToFoo
zuzuweisen, gibt der Compiler Ihnen einen Fehler, wenn Sie versuchen, die Referenz selbst zu ändern:
Sie müssen daher referenceToFoo
a var
angeben, um diese Zuweisung legal zu machen.
struct
ist ein Werttyp. Wenn Sie sie bearbeiten, rufen Sie den Standard-Setter für die Eigenschaft auf, der nichts anderes als eine Mutationsmethode ist, die nichts anderes als eine statische Methode der Struktur ist, die self
als erstes Argument hat wie inout
, die die Methode zurückgibt (Swift für jetzt hat Curry-Syntax für nicht angewandte Methodenaufrufe, aber wird das ändern zu einem abgeflachten ). Nur als Randnotiz: Wenn die Methode nicht mutiert, wird sie nicht inout
sein.
Weil inout
arbeitet, indem kopiert ein - auskopiert , wird didSet
aufgerufen, auch wenn sich nichts geändert hat.
"Wenn Sie eine Eigenschaft mit Beobachtern an eine Funktion als In-Out-Parameter übergeben, werden die Beobachter von" willSet "und" didSet "immer aufgerufen." Auszug aus: Apple Inc. "Die schnelle Programmiersprache (Swift 3)." IBooks. Ссылка
Code, den ein var
struct kopiert, wenn eine Eigenschaft mutiert ist:
Ruft das didSet
auf, obwohl wir nur das Int in der Eigenschaft der Struktur mutiert haben.
Wenn es eine komplett neue Kopie wäre, dann würden Sie erwarten, dass die mutierte Struktur eine neue Kopie mit neuer Speicherzuweisung ist. Dies ist jedoch nicht der Fall in dem Beispiel, siehe Code unten.
%Vor% Also wird die Struktur nicht kopiert. Aber weil es inout
ist:
"Schreiben Sie Ihren Code unter Verwendung des Modells, das durch Kopieren-in-Kopie angegeben wird, ohne von der call-by-reference-Optimierung abhängig zu sein, so dass es sich korrekt mit oder ohne Optimierung verhält." Auszug aus: Apple Inc. "Die schnelle Programmiersprache (Swift 3)." IBooks. Ссылка
inout
only: