Wann gibt -copy ein veränderbares Objekt zurück?

8

Ich lese in Kakao und Ziel C: Auf und ab , dass -copy immer zurückkehrt Ein unveränderliches Objekt und -mutableCopy geben immer ein veränderbares Objekt zurück:

  

Es ist wichtig zu wissen, dass das Aufrufen von -copy auf einem veränderbaren Objekt ein unveränderliches Objekt zurückgibt   Ausführung. Wenn Sie ein änderbares Objekt kopieren und die Änderbarkeit in der neuen Version beibehalten möchten,   Sie müssen -mutableCopy für das Original aufrufen. Dies ist jedoch nützlich, wenn Sie möchten   Um ein veränderbares Objekt "einzufrieren", können Sie einfach -copy aufrufen.

Ich habe also so etwas:

%Vor%

Nach dieser vorherigen Antwort :

  

Sie können sich nicht darauf verlassen, dass das Ergebnis der Kopie veränderbar ist! Kopieren eines NSMutableArray kann   gib ein NSMutableArray zurück, da das die ursprüngliche Klasse ist, aber beliebig kopieren    NSArray Instanz würde nicht.

Dies scheint etwas isoliert zu NSURLRequest zu sein, da NSArray wie vorgesehen funktioniert:

%Vor%

Also ...

  1. Wann gibt -copy ein unveränderliches Objekt zurück (wie erwartet) und wann gibt es ein veränderbares Objekt zurück?
  2. Wie erreiche ich den beabsichtigten Effekt, eine "eingefrorene" Kopie eines veränderlichen Objekts zu erhalten, das nicht "eingefroren" werden kann?
rubergly 27.08.2011, 02:56
quelle

4 Antworten

12

Ich denke, Sie haben eine große Kluft zwischen Dokumentation und Realität aufgedeckt.

Die NSCopying-Protokolldokumentation behauptet:

  

Die zurückgegebene Kopie ist unveränderlich, wenn die Betrachtung "unveränderlich vs. veränderbar" für das empfangende Objekt gilt; Andernfalls wird die genaue Art der Kopie durch die Klasse bestimmt.

Aber das ist in einigen Fällen eindeutig falsch, wie Sie in Ihren Beispielen gezeigt haben (und ich habe ihnen über diese Dokumentationsseite Feedback dazu geschickt).

Aber (# 2) meiner Meinung nach spielt es eigentlich keine Rolle, und Sie sollten sich nicht darum kümmern.

Der Punkt von -copy ist, dass es ein Objekt zurückgibt, das verwendet, mit der Garantie, dass es sich unabhängig vom Original verhält. Dies bedeutet, wenn Sie ein veränderbares Objekt haben, -copy es, und ändern Sie das ursprüngliche Objekt, die Kopie wird nicht den Effekt sehen. (In manchen Fällen bedeutet dies, dass -copy optimiert werden kann, um nichts zu tun, denn wenn das Objekt unveränderlich ist, kann es nicht von vornherein geändert werden. Ich kann mich deswegen irren. (Ich frage mich jetzt was die Implikationen für Dictionary Keys aus diesem Grund sind, aber das ist ein separates Thema ...))

Wie Sie gesehen haben, kann das neue Objekt in einigen Fällen eine veränderbare Klasse sein (auch wenn die Dokumentation es nicht sagt). Aber solange du dich nicht darauf verlässt, dass es veränderbar ist (warum würdest du?), Ist es egal.

Was sollten Sie tun? Behandle das Ergebnis von -copy immer als unveränderlich , einfach so.

    
jtbandes 27.08.2011, 04:00
quelle
3
  

1) Wann gibt -copy ein unveränderliches Objekt zurück (wie erwartet) und wann gibt es ein veränderbares Objekt zurück?

Sie sollten es immer als die unveränderliche Variante behandeln. Die änderbare Schnittstelle des zurückgegebenen Typs sollte nicht verwendet werden. Abgesehen von Optimierungen sollte die Antwort keine Rolle spielen und sollte als Implementierungsdetail betrachtet werden, sofern nicht dokumentiert.

Der offensichtliche Fall: Objc-Klassencluster und Klassenentwürfe können aus einer Reihe von Gründen komplex sein. Die Rückgabe einer veränderbaren Kopie könnte einfach nur der Bequemlichkeit dienen.

  

2) Wie erreiche ich den beabsichtigten Effekt, eine "eingefrorene" Kopie eines veränderbaren Objekts zu erhalten, das nicht "eingefroren" werden kann?

mit dem Kopierkonstruktor der unveränderlichen Klasse ist ein guter Weg (ähnlich der Antwort von St3fan). wie copy , es ist keine Garantie.

Der einzige Grund, warum ich mir vorstellen kann, warum Sie dieses Verhalten erzwingen möchten, ist die Leistung oder die Durchsetzung einer eingeschränkten Schnittstelle (es sei denn, es ist akademisch). Wenn Sie eine Performance oder eine eingeschränkte Schnittstelle wünschen, können Sie einfach eine Instanz des Typs kapseln, der bei der Erstellung kopiert wird, und nur die unveränderliche Schnittstelle verfügbar machen. dann implementieren Sie kopieren über behalten (wenn das Ihre Absicht ist).

Alternativ können Sie Ihre eigene Unterklasse schreiben und Ihre eigene Variante der Kopie implementieren.

letzter Ausweg: Viele der veränderbaren / unveränderlichen Kakao-Klassen sind reine Schnittstellen - Sie könnten Ihre eigene Unterklasse schreiben, wenn Sie ein bestimmtes Verhalten sicherstellen müssen - aber das ist ziemlich ungewöhnlich.

vielleicht eine bessere Beschreibung, warum dies durchgesetzt werden sollte, wäre gut - die vorhandenen Implementierungen funktionieren gut für die überwiegende Mehrheit der Entwickler / Anwendungen.

    
justin 27.08.2011 04:18
quelle
1

Bedenken Sie, dass es keine copy -Implementierung gibt - jede Klasse implementiert ihre eigene. Und wie wir alle wissen, ist die Implementierung der Objective-C-Laufzeit ein wenig "loosey goosey" in Punkten. Also ich denke, wir können sagen, dass meist copy eine unveränderbare Version zurückgibt, aber einige Ausnahmen existieren.

(Übrigens, was macht das?

%Vor%

?)

    
Hot Licks 27.08.2011 03:03
quelle
-1

Der beste Weg, ein Objekt in ein veränderbares Objekt zu verwandeln, ist der veränderbare 'Konstruktor'. Wie zum Beispiel:

%Vor%

Kopieren wird verwendet, um eine Kopie eines Objekts zu erstellen. Um es nicht zu verändern ist es möglich.

    
Stefan Arentz 27.08.2011 03:53
quelle