0

明確化: 問題は、変更可能か不変かについてではなく、正しいクラスのインスタンスを作成するスーパーへの呼び出しについてです。[[self class] alloc]基本クラスで使用することは考えていませんでしたが、これで問題が解決するようです。何も良いことがない場合は、次の数時間でその anser を受け入れます :)


Apple の仕様には次のように書かれています。

If a subclass inherits NSMutableCopying from its superclass and declares
additional instance variables, the subclass has to override mutableCopyWithZone:
to properly handle its own instance variables, invoking the superclass’s
implementation first.

それは非常に紛らわしいです。検討

@interface Base : NSObject<NSMutableCopying>
@property (nonatomic, assign) NSInteger value ;
@end
@implementation Base
...
@end


@interface Derived : Base<NSMutableCopying>
@property (nonatomic, assign) NSInteger value2 ;
@end

@implementation Derived

- (id) mutableCopyWithZone: (NSZone *) zone {
    // Huh ???
    Derived * derived = [super mutableCopyWithZone: zone] ;
    ...
    // Huh ??????
    derived.value2 = self.value2 ;
    return derived ;
}
...
@end

仕様に従った場合、このコードがどのように正しい可能性があるのか​​ わかりません。

への呼び出しが[super mutableCopyWithZone: zone]返されたとき、基本クラスは独自の ivar に十分なスペースしか割り当てていないと予想しています。Derivedインスタンスが独自の ivar 用により多くのスペースを必要としていると判断する方法はありません。

ドキュメントが意味することは、実際には何ですか? これをどのように実装すればよいですか?

4

1 に答える 1

4

super は、ディスパッチの方法を変更するだけです (動的ではなく静的)。しかし、それは受信者を変更しません。アップキャストは行いません。-mutableCopyWithZone: (super) self はまだ派生クラスのインスタンス オブジェクトを指しています。

スーパー メソッド (またはスーパー スーパー メソッドなど) が適切な方法でオブジェクトの作成を実装していない場合、問題が発生する可能性があります。

copy = [[BaseClass alloc] init]; // Wrong, an instance of the base class is created

copy = [[[self class] alloc] init]; // Correct, an instance of [self class] == DerivedClass is created

2 番目の方法を使用すると、派生クラスのインスタンスを取得し、ivar のメモリがいっぱいになります。

結論: BaseClass が -mutableCopyWithZone: を適切に実装している場合は、この方法で実装してください。それ以外の場合は、独自のコピーを作成して初期化する以外に変更はありません。

私がいつも書いている本の中で、クラス内でクラス名を使用する理由はほとんどないと書いています。[self class] (インスタンス メソッド内) と self (クラス メソッド内) を使用することは、99% より良いアプローチです。

于 2013-05-29T07:27:55.853 に答える