#import <stdio.h>
#import <objc/Object.h>
@interface Test : Object
- (void) msg;
@end
@implementation Test
- (void) msg {
printf("Hello world!\n");
}
@end
int main(int argc, char** argv) {
id obj = [Test alloc];
[obj msg];
return 0;
}
$ gcc hello.m -lobjc
NSString を使ってみる
#import <stdio.h>
#import <objc/Object.h>
#import <Foundation/NSString.h>
@interface Test : Object
{
id name;
}
- (void) msg;
@end
@implementation Test
- (void) setName:(NSString*)name_ {
[name release];
name = name_;
}
- (void) msg {
NSLog(@"Hello %@!\n", name);
}
@end
int main(int argc, char** argv) {
id obj0 = [Test alloc];
[obj0 setName:@"amachang"];
id obj1 = [Test alloc];
[obj1 setName:@"prochang"];
[obj0 msg];
[obj1 msg];
return 0;
}
$ gcc hello.m -lobjc -framework Foundation
- NSString は @"hoge" って感じでつくれる
- インスタンス変数は中括弧で、 @interface の中で宣言する
- NSString や NSLog を使うにはは Foundation フレームワークが要る(-framework Foundation)
- id はやっぱりポインタ? id のところを NSString* にしても同じ結果だった。
- NSString は release メッセージで参照カウンタを下げる(あげるときは retain 、alloc 時には自動で retain される)
Object より NSObject のほうがいいのかな?
- Object で release を呼び出してみると warning が出た
- NSObject にしたら大丈夫だった
NSAutoreleasePool と autorelease
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
@interface Foo : NSObject @end
@implementation Foo
-(void) dealloc {
NSLog(@"dealloc Foo");
[super dealloc];
}
@end
int main(int argc, char** argv) {
id arp = [[NSAutoreleasePool alloc] init];
id obj0 = [[Foo alloc] init];
[obj0 autorelease];
id obj1 = [[Foo alloc] init];
[obj1 autorelease];
NSLog(@"release arp");
[arp release];
return 0;
}
$ gcc hello.m -lobjc -framework Foundation && ./a.out
2008-04-21 17:20:03.198 a.out[30050:10b] release arp
2008-04-21 17:20:03.200 a.out[30050:10b] dealloc Foo
2008-04-21 17:20:03.201 a.out[30050:10b] dealloc Foo
- NSAutoreleasePool を作っておいて release ではなくて autorelease を送っておくと NSAutoreleasePool が解放されるタイミングで解放される。
- release で参照カウンタが 0 になると dealloc が呼ばれる
- dealloc をオーバーライドすればデストラクタとして使える
- super にメッセージを遅れば、継承もとのメソッドを呼べる
ダックタイピング
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
@interface Foo : NSObject @end
@implementation Foo
-(id) msg {
NSLog(@"foo");
return self;
}
@end
@interface Bar : NSObject @end
@implementation Bar
-(id) msg {
NSLog(@"bar");
return self;
}
@end
int main(int argc, char** argv) {
srand(time(NULL));
[[[[rand()%2 ? [Foo class] : [Bar class]
alloc] init] msg] release];
return 0;
}
- メソッドの呼び出しはメッセージなので、ダックタイピングな書き方ができる(上の例の Foo と Bar)
- this じゃなくて self
- [Bar alloc] と [[Bar class] alloc] は同じ(?)。 Bar は式の中に書けないけど、 [Bar class] は式の中に書ける