2009-05-25

Objective-Cのオブジェクト指向機能の練習

MacBookを買ってiPhoneアプリを作ることにした私ですが、どうやらiPhoneアプリ(というかマックアプリ)はObjective-Cという言語を使って作る必要があるようで、まずはその言語を覚えることにしました。

Objective-CはANSI Cに独自のオブジェクト指向機能を追加した言語。なので基本的にC言語なのでHello worldとかエラトステネスの篩とかお約束は省略します。オブジェクト指向機能をどんな感じで使えば良いかだけ練習してみました。本当のObjC初心者なので超初歩的内容ですので注意!

まずObamaクラスを書いてみました。

【クラスを定義してみる】
/**
* Objective-Cのオブジェクト指向機能のテスト
* 2009-05-23
*
*/

#include <stdio.h>
#include <Foundation/NSObject.h>

@interface Obama : NSObject
{
BOOL isElection;
}
-(id)init;
-(void)election: (BOOL)b;
-(void)whoAreYou;
-(void)speach;
@end

@implementation Obama
-(id)init { isElection = FALSE; }
-(void)election: (BOOL)b { isElection = b; }
-(void)whoAreYou
{
if (isElection == TRUE)
printf("I'm President Obama!\n");
else
printf("I'm Obama!\n");
}
-(void)speach { printf("Yes, we can!\n"); }
@end

int main()
{
id objObama = [[Obama alloc] init];
printf("class Obama\n");
[objObama speach];
[objObama whoAreYou];
[objObama election: TRUE];
[objObama whoAreYou];

return 0;
}


まずクラスを定義するにはFoundationというフレームワークのNSObjectというのを継承しなければいけないようです。FoundationはWinプログラムでいうMFCみたいなものかな? 
で、@interface ... @endまでがクラス定義。最初の{}にクラス変数を書いて、あとはメンバ関数の宣言。メンバ関数の実装は@implementation ... @endで記述する。「なんでメンバ関数の先頭にハイフン付けるんだろう?」とか「引数を:のあとに書くのは違和感あるなあ」とかいろいろ思うところはありますが、とりあえずこれでクラスは作れた。

ちなみにここまでの作業はTerminal.appを立ち上げてemacsで書きました。Windowsと違ってCygwinを入れなくても素でUNIXなのは楽ですねー。上のプログラム、本当は@interface部をヘッダーファイル(.h)、@implementationをプログラムファイル(.m)に書いてmain.mにインクルードするのが王道でジャスティスみたいなのですが、ここではめんどいので1ファイルに全部書いてます(ファイル名はclass_test.mとしときます)

クラス定義まではC++をやったことある人なら、何となく分かるでしょう。でもその後のmain関数の中のインスタンス作成、メッセージ送信はちょっと見慣れない書式です。要するに関数呼び出しのことをメッセージ送信と呼んでいるみたいです。オブジェクト指向のモデルがSmalltalk的で、むしろC++よりこっちのほうが王道かもしれないっすね。
まずはallocでインスタンス作成、初期化したいときはinit関数を作るとだけ覚えておけば大丈夫そう。

あとはコンパイル。GCCを使います。
gcc class_test.m -framework Foundation

これでカレントディレクトリにa.outという実行ファイルができます。ちなみに実行するとこうなります。

class Obama
Yes, we can!
I'm Obama!
I'm President Obama!




【Obamaクラスを継承して多態性を試す】

さっきのObamaクラスを継承してNocchiクラスを作ってみます(ネタが古いとか突っ込みはガン無視の方向で)。

/**
* Objective-Cのオブジェクト指向機能のテスト
* 2009-05-23
*
*/


#include <stdio.h>
#include <Foundation/NSObject.h>

@interface Obama : NSObject
{
BOOL isElection;
}
-(id)init;
-(void)election: (BOOL)b;
-(void)whoAreYou;
-(void)speach;
@end

@implementation Obama
-(id)init { isElection = FALSE; }
-(void)election: (BOOL)b { isElection = b; }
-(void)whoAreYou
{
if (isElection == TRUE)
printf("I'm President Obama!\n");
else
printf("I'm Obama!\n");
}
-(void)speach { printf("Yes, we can!\n"); }
@end

@interface Nocchi : Obama {}
-(void)speach;
-(void)sayJoke;
@end

@implementation Nocchi
-(void)speach { printf("イエス、ウィ キャン!\n"); }
-(void)sayJoke { printf("のっちで〜す!\n"); }
@end

int main()
{
id objObama = [[Obama alloc] init];
printf("class Obama\n");
[objObama speach];
[objObama whoAreYou];
[objObama election: TRUE];
[objObama whoAreYou];

id objNocchi = [[Nocchi alloc] init];
printf("class Nocchi\n");
[objNocchi speach];
[objNocchi sayJoke];

return 0;
}


これの実行結果は以下。

class Obama
Yes, we can!
I'm Obama!
I'm President Obama!
class Nocchi
イエス、ウィ キャン!
のっちで〜す!


うむ、speach関数のところがちゃんと上書きされておる。これでとりあえずクラスの定義、インスタンスの生成、クラスの継承まで一通りできました。超初歩的な内容ですが、自分の備忘録として記事にしてみました。


あとはまだまだ疑問点があります。また調べて記事にしてみよう。
  • allocでインスタンス生成をしたあとにメモリ解放はしなくていいのか?(malloc/free的なノリで)
  • メッセージは変数化できないのか? C言語の関数ポインタみたいに使えるとメタなプログラミングができて面白そう。

しかし新しい言語を勉強するのは久しぶりですが、やっぱり楽しいですね〜。ざっと解説本を眺めてみましたけど、C++よりは簡単そうでほっとしてます。さあ、いろいろ試すぞ!

2 件のコメント:

laiz さんのコメント...

新しい言語か~良いね~♪
新しい言語覚えてる時の
なんでこんな書き方するの?って感覚。
あれが慣れてだんだん消えてくのが
楽しいよね~♪

ってか、ほんっとにオバマさん好きだね(笑
Obamaクラスって(笑

deltam さんのコメント...

> Laiz

やっぱり新しい言語を覚えてく時の感覚は独特だね。出来ることがだんだん増えていくのは純粋に面白い!

> ってか、ほんっとにオバマさん好きだね(笑

smart.fm(旧iKnow!)でオバマさんの演説を教材にしているんで、ほぼ毎日スピーチを聞いてます。洗脳されてきたのかな?w