9

私はCocoaとObjectiveC:Up and Runningを読みました。これ-copyは常に不変オブジェクトを-mutableCopy返し、常に可変オブジェクトを返します。

可変オブジェクトを呼び出す-copyと、不変バージョンが返されることを知っておくことが重要です。可変オブジェクトをコピーして新しいバージョンで可変性を維持したい場合は-mutableCopy、元のオブジェクトを呼び出す必要があります。ただし、これは便利です。可変オブジェクトを「フリーズ」したい場合は、-copyそれを呼び出すだけでよいからです。

だから私はこのようなものを持っています:

NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
NSLog( @"%@", [req className] );               // NSMutableURLRequest
NSLog( @"%@", [[req copy] className] );        // NSMutableURLRequest
NSLog( @"%@", [[req mutableCopy] className] ); // NSMutableURLRequest

この前の答えによると:

コピーの結果が変更可能であると信頼することはできません。をコピーすると、元のクラスであるため、NSMutableArrayが返される場合がありますがNSMutableArray、任意の NSArrayインスタンスをコピーすると返されません。

意図したとおりに機能するためNSURLRequest、これはやや孤立しているようです。NSArray

NSArray *arr = [[NSMutableArray alloc] init];
NSLog( @"%@", [arr className] );                 // __NSArrayM
NSLog( @"%@", [[arr copy] className] );          // __NSAraryI
NSLog( @"%@", [[array mutableCopy] className] ); // __NSArrayM

それで...

  1. -copy(期待どおりに)不変オブジェクトを返すのはいつですか?また、可変オブジェクトを返すのはいつですか?
  2. 「凍結」を拒否する可変オブジェクトの「凍結」コピーを取得するという意図された効果をどのように達成しますか?
4

4 に答える 4

13

ドキュメントと現実の間の大きな亀裂を発見したと思います。

NSCopying プロトコルのドキュメントには次のように記載されています。

「不変対可変」という考慮事項が受信オブジェクトに適用される場合、返されるコピーは不変です。それ以外の場合、コピーの正確な性質はクラスによって決定されます。

しかし、あなたの例で示したように、これは明らかに間違っている場合があります (そして、そのドキュメントページを介して、これに関するフィードバックを彼らに送りました)。

しかし(#2) 私の意見では、実際には問題ではなく、気にする必要はありません。

ポイントは、元のオブジェクトとは独立して動作することを保証して、-copy使用できるオブジェクトを返すことです。これは、変更可能なオブジェクトがあり、元のオブジェクトを変更した場合、コピーには効果が見られないことを意味します。(場合によっては、これは何もしないように最適化できることを意味すると思います。オブジェクトが不変である場合、そもそも変更できないためです。これについては間違っている可能性があります。このため、辞書キー用ですが、それは別のトピックです...))-copy-copy

これまで見てきたように、場合によっては、新しいオブジェクトが実際には変更可能なクラスである可能性があります (ドキュメントでは変更できないと記載されていても)。しかし、変更可能であることに依存しない限り (なぜそうする必要があるのでしょうか?)、それは問題ではありません。

あなたは何をするべきか?の結果は常に-copyimmutable として扱い、そのようにシンプルにします。

于 2011-08-27T04:00:57.993 に答える
3

1)-copyはいつ不変オブジェクトを返しますか(期待どおり)、いつ可変オブジェクトを返しますか?

常に不変のバリアントとして扱う必要があります。返されたタイプの可変インターフェースは使用しないでください。最適化は別として、答えは重要ではなく、文書化されていない限り、実装の詳細と見なす必要があります。

明らかなケース:いくつかの理由で、objcクラスクラスターとクラスデザインは複雑になる可能性があります。変更可能なコピーを返すことは、単に便宜のためである可能性があります。

2)「凍結」を拒否する可変オブジェクトの「凍結」コピーを取得するという意図された効果をどのように達成しますか?

不変クラスのコピーコンストラクターを使用するのは良い方法です(St3fanの答えと同様)。のようcopyに、それは保証ではありません。

この動作を強制する理由について私が考えることができる唯一の理由は、パフォーマンスのため、または制限されたインターフェイスを強制するためです(アカデミックでない限り)。パフォーマンスまたは制限されたインターフェイスが必要な場合は、作成時にコピーし、不変のインターフェイスのみを公開するタイプのインスタンスをカプセル化するだけです。次に、retainを介してコピーを実装します(それがあなたの意図である場合)。

または、独自のサブクラスを作成して、独自のコピーのバリアントを実装することもできます。

最後の手段:カカオの可変/不変クラスの多くは純粋にインターフェースであり、特定の動作を保証する必要がある場合は独自のサブクラスを作成できますが、これは非常に珍しいことです。

おそらく、これを強制する必要がある理由をより適切に説明することをお勧めします。既存の実装は、大多数の開発者/使用者にとって問題なく機能します。

于 2011-08-27T04:18:43.713 に答える
1

実装は 1 つではなく、copy各クラスが独自に実装していることに注意してください。そして、誰もが知っているように、Objective C ランタイムの実装は、ところどころ「ゆるいグージー」です。したがって、ほとんど の場合、不変のバージョンを返すと言えcopyますが、いくつかの例外が存在します。

(ところで、これは何をしますか:

NSArray *arr = [[NSMutable array] init];

?)

于 2011-08-27T03:03:37.883 に答える
-1

オブジェクトを変更可能なオブジェクトに変換する最良の方法は、変更可能な「コンストラクタ」を使用することです。たとえば、次のようにします。

NSArray* array = ...;
NSMutableArray* mutableArray = [NSMutableArray arrayWithArray: array];

Copy は、オブジェクトのコピーを作成するために使用されます。その可変性を変更しないでください。

于 2011-08-27T03:53:18.240 に答える