+initialize はクラスのイニシャライザ(初期化メソッド)。クラスがロードされた時に呼び出される。これが2度呼ばれることがある(状況によってはさらに複数回呼び出される)。
Mac Dev Center にそんな情報があった。
Mac Dev Center: Coding Guidelines for Cocoa: Tips and Techniques for Framework Developers
試してみよう。
ParentClass とそれを継承した ChildClass を作る。
ParentClass.h
@interface ParentClass : NSObject {
}
@end
ParentClass.m
#import "ParentClass.h"
@implementation ParentClass
+ (void)initialize
{
NSLog(@"initialize: %@", self);
}
@end
ChildClass.h
#import "ParentClass.h"
@interface ChildClass : ParentClass {
}
@end
ChildClass.m
#import "ChildClass.h"
@implementation ChildClass
@end
+initialize は ParentClass のみ実装し、ChildClass では実装しない。
これを実行時に、例えば AppDelegate などでインスタンス化する。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
// [ChildClass self];
[[ChildClass alloc] init];
}
結果はこう。
Test[1116:80f] initialize: ParentClass
Test[1116:80f] initialize: ChildClass
ParentClass の +initialize が2回呼び出されいている。これはランタイムが使用するクラスへ +initialize を投げるのだが、派生クラスに実装がない場合は親クラスのメソッドが呼び出されるため(そういう意味ではクラスメソッドも、インスタンスメソッド同様にメッセージのルーティングが行われている)。
試しに ChildClass.m に +initialize を実装してみる。
#import "ChildClass.h"
@implementation ChildClass
+ (void)initialize
{
NSLog(@"initialize in ChildClass: %@", self);
}
@end
結果はこう。
Test[1199:80f] initialize: ParentClass
Test[1199:80f] initialize in ChildClass: ChildClass
先のりファンレスでは初期化処理が複数回呼び出されるのを避ける為に self をチェックするのが良いと書かれていた。
こんな感じ。
#import "ParentClass.h"
@implementation ParentClass
+ (void)initialize
{
if (self == [ParentClass class]) {
NSLog(@"initialize: %@", self);
}
}
@end
ChildClass の initialize を消して再び実行すると:
Test[1250:80f] initialize: ParentClass
派生クラスが想定される場合、親となるクラスでの +initialize を実装する場合は気を付ける必要がある。