Big Nerd Ranch の iOS Programming Book (第 3 版) の pg.194 には、知識のあるプログラマーが allocWithZone: を介して BNRItemStore のインスタンスを作成する可能性があると書かれています。 BNRItemStore.m で、単一の BNRItemStore インスタンスを返します。
+(id) allocWithZone:(NSZone *)zone
{
return [self sharedStore];
}
このステートメントは、私には混乱しているように思えます。この次のコードは、ある意味でこれが間違っていることを証明していませんか?
#import <Foundation/Foundation.h>
@interface BNRItemStore : NSObject
+(BNRItemStore *)sharedStore;
+(id)retrieveObject;
@end
@implementation BNRItemStore
+(BNRItemStore *)sharedStore{
static BNRItemStore *sharedStore=nil;
if (!sharedStore){
NSLog(@"Test2");
sharedStore= [[super allocWithZone:nil] init];
}
NSLog(@"sharedStore-> %@",sharedStore);
return sharedStore;
}
+(id)allocWithZone:(NSZone *)zone{
NSLog(@"Test1");
return [self sharedStore];
}
+(id)alloc{
NSLog(@"Retrieving super object");
NSLog(@"%@", [super allocWithZone:nil]);//Bypassing the subclass version of allocWithZone.
return [super allocWithZone:nil];
}
@end
int main(){
[[BNRItemStore alloc] init]; //the alloc message triggers a call to the subclass (overriding) version of +(id)alloc method
}
出力は次のとおりです。
- 2013-10-18 18:24:40.132 BNRItemStore[381:707] スーパー オブジェクトの取得
- 2013-10-18 18:24:40.134 BNRItemStore[381:707] BNRItemStore:0x7f8c72c091e0
サブクラスの 'alloc' メソッド内の [super allocWithZone:nil] 呼び出しがサブクラスの allocWithZone への呼び出しをトリガーした場合、コンソールは "Test1" と "Test2" をログに記録し、最終的に静的ポインターが割り当てられることになります。しかし、これは起こりませんでした。これは、[NSObject allocWithZone:nil] または [super allocWithZone:nil] を直接呼び出すと、メッセージは allocWithZone のオーバーライド バージョン (サブクラス バージョン) にリダイレクトされず、実際の処理を行う NSAllocateObject() 関数に直接アクセスできることを意味します。割り当て。NSObject の +(id)allocWithZone のコードは、次のようになります。
+(id)allocWithZone:(NSZone *)zone{
return NSAllocateObject();
}
この実装 (NSObject の allocWithZone:) に [self allocWithZone] のようなものが含まれていた場合、メッセージ ディスパッチ メカニズムには allocWithZone のサブクラス バージョンが含まれており、sharedStore メソッドの呼び出しを含む「卑劣な」トラップを通過することになります。私が話しているケース。この場合、コードは間違いなく無限ループになります。明らかに、そうではありません。
+(id)allocWithZone:(NSZone *)zone{
if([self allocWithZone:zone]) //this would trigger a call to subclass ver. which would call sharedStore method which would then have [super allocWithZone:nil].Infinite Loop
return NSAllocateObject();
}
誰かがこのいわゆる「卑劣な」トラップに関するこのクエリをクリアできますか。トラップは、誰かが個別にインスタンス化するのをブロックするためのものでした.つまり、sharedStoreメソッド内以外ではNSObjectのallocWithZoneを使用できませんか? Plsは明確に..