ソースファイルの構造は:
--------------
1. Song.h
2. Song.m
3. Singer.h
4. Singer.m
5. main.m
6. GNUmakefile
--------------
図に示すと,
上記の図では, Singer.h で Song.h の読み込みが指示され, さらに main.m では Song.h と Singer.h の両方の読み込みが指示されているので, main.m において Song.h が 2 度読み込まれているように見えるが, #import では同一のヘッダファイルが 2 重に読み込まれることはない.
1 2 3 4 5 6 7 8 9 10 11 12 | #import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
// Song クラスの宣言
@interface Song : NSObject{
NSString *lyrics;
}
- (NSString *) lyrics;
- (void) setLyrics: (NSString *)argLyrics;
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #import "Song.h"
// Song クラスの実装
@implementation Song : NSObject
- (NSString *) lyrics{
return lyrics;
}
- (void) setLyrics: (NSString *)argLyrics{
lyrics = argLyrics;
}
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 | #import <Foundation/NSObject.h>
#import <stdio.h>
#import "Song.h"
// Singer クラスの宣言
@interface Singer : NSObject{
Song *song;
}
- (void) setSong: (Song *)argSong;
- (void) sing;
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 | #import "Singer.h"
// Singer クラスの実装
@implementation Singer : NSObject
- (void) setSong: (Song *)argSong{
song = argSong;
}
- (void) sing{
printf( "the song is: %s\n", [[song lyrics] UTF8String] );
}
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #import <Foundation/Foundation.h>
#import "Song.h"
#import "Singer.h"
// 実行プログラム
int main(int argc, char *argv[]){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id song;
id singer;
song = [[Song alloc] init];
[song setLyrics:@"La La La ..."];
singer = [[Singer alloc] init];
[singer setSong:song];
[singer sing];
[pool drain];
return 0;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | .SUFFIXES: .o .m
.m.o:
$(CC) -c $(CFLAGS) $<
PROG = main
CC = gcc
CFLAGS = -g -Wall
FRAMEWORKS = -framework Foundation
SRC = Song.m Singer.m main.m
OBJ = Song.o Singer.o main.o
hist: $(OBJ)
$(CC) $(CFLAGS) -o $(PROG) $(OBJ) $(FRAMEWORKS)
.PHONY: clean
clean:
$(RM) $(PROG) $(OBJ) *~ a.out
Song.o: Song.h Song.m
Singer.o: Singer.h Singer.m
main.o: Song.h Singer.h main.m
|
main.m の実行結果は:
[wtopia 2]$ ./main
the song is: La La La ...
クラス名は, @interface に続けて:
クラス名 : スーパークラス名
のように記述する.
通常, あらゆるクラスがこの NSObject クラスの直接または間接的なサブクラスとして定義されるため, NSObject クラスはルートクラスとも呼ばれる.
クラス型の変数は, いわゆるポインタとして宣言する必要がある.
ポインタは, クラスの実体が保存されているメモリ上のアドレスを表す変数で, 変数名の前に * を付けて宣言する.
クラス型の変数が常にポインタであることで, プログラム内での変数の受け渡し時に, 常に同じ実体を指し示すことができる.
Objective-C におけるメソッドの記述方法は独特で, この言語の大きな特徴でもある.
先頭の - に続く () 内には, メソッドの戻り値の型 (なければ, void にする), 続いてメソッド名を記述する. 引数がある場合には, 続けて : (コロン), 引数の型 (これも () 内に記述), 後は引数名のように記述する.
Song クラスの lyrics メソッドや setLyrics メソッド, および Singer クラスの setSong メソッドは, 単にクラスのメンバ変数の値を取得したり, 新たに値をセットしたりするだけのもの. このようなメソッドを, 変数に対するアクセサト呼ぶ.
クラスのオブジェクトを保存するために, 汎用的な型である id 型の変数を用意する. id 型の場合は * でポインタであることを明示する必要がない.
alloc と init は, あるクラスの実体を生成して初期化するための定番メソッドで, 両メソッドとも, ルートクラスである NSObject に定義されているので, 自作のクラスで独自に定義していなくても利用できる.
メッセージ式は, Song クラスや Singer クラスに対して alloc メソッドを実行するようメッセージを送り, さらにその戻り値であるクラスの実体に対して init メソッドを実行するようにメッセージを送る.