しつこくオブジェクトシステムの話。
http://d.hatena.ne.jp/shinichiro_h/20051213#1134403952
の続きなんだけど、とりあえずポージングは全然違った。
state遷移の話。例えば敵オブジェクトが弾に当たって適当な爆発エフェクトになる、っていうヤツを実装する時、OOでやると同じ位置に別なオブジェクトを作ってそいつを登録して自己削除して、みたいなことになっちゃうことが多いわけです。
んでも実際にやりたいことはただ仮想関数テーブルを入れ替えるだけでいいわけ。タスクシステムだったらたぶんタスクの型を変えるだけでいいんでしょう。要はx,yだのの情報は残しつつ、所属クラスだけを変えたい。 Objective-C はこれできるよなーということでして。
- (void)transform:c { self->isa = c; }
適当にこんなのを定義しておいて、後は [beforeObject.transform:[AfterClass class] ]; とかで変身。いやぁ簡単。
以下サンプルコード。
最初は Right クラスですが、右にちょっと移動すると Left クラスになって左に行き、そんでまた Right に変身しなおしています。
#import <stdio.h> #import <objc/Object.h> @interface Base : Object { int x; } - (void)transform:c; @end @interface Right : Base - (id)init; - (void)move; @end @interface Left : Base - (id)init; - (void)move; @end @implementation Base - (void)transform:c { self->isa = c; } @end @implementation Right - (id)init { x = 0; } - (void)move { x++; printf("%d\n", x); if (x > 2) { printf("transform\n"); [self transform:[Left class]]; } } @end @implementation Left - (id)init { x = 0; } - (void)move { x--; printf("%d\n", x); if (x <= 0) { printf("transform\n"); [self transform:[Right class]]; } } @end int main() { id o = [Right new]; for (int i = 0; i < 10; i++) { [o move]; } return 0; }
出力は以下のような感じ。
1 2 3 transform 2 1 0 transform 1 2 3 transform 2