他の言語を習得している人がObjective-Cを勉強しようとすると、
独特の構文や不思議なキーワードが登場して、大抵面食らうと思います。
膨大な数のAPIに圧倒されることもあって、
何から手をつけていいのやらわからなくなるようです。
C++, Java辺りを知っている人が習得する場合は、
まず、Objective-Cの構文やキーワードと、
自分の知っている構文やキーワードと、どう関係があるのかを知ることが、
一番の近道ではないかと思います。
ということで、Objective-Cの主要キーワードを概要だけ、ざらっと解説します。
ちなみに、Cの完全上位互換ですので、Cで使えるものはObjective-Cでも使えます。
@interface
クラスを宣言します。インタフェースと書いてありますが、はっきり言ってクラスです。
メソッドの呼び出し
[object メソッド名]で呼び出します。
アロー演算子(->)やドット(.)では呼び出せません。
ちなみに、不明なメソッドを呼び出そうとしても、コンパイルは通ります。
実行時にメソッドが見つからない場合、実行時エラーが発生します。
@implementation
@interfaceで宣言したクラスの実装を書く部分です。@protocol
プロトコルは、JavaやC++あたりでいうところのインタフェースです。ただ、Objective-Cのプロトコルは、デリゲート以外で使われることはほとんどありません。
ちなみにデリゲートはGOFのTemplate Methodだと思っておけば大体あっていると思います。
@property
@propertyは、setter, getterアクセサを宣言します。@property (オプション) 型 プロパティ名
のように使います。
C#やActionScriptなどにもアクセサ生成がありますが、
それに比べると、オプションがやたら豊富です。
この機能はよく使いますので、詳しく調べておくと便利です。
ちなみにプロパティは、ドット構文でアクセスできます。
@synthesize
propertyで宣言されたプロパティのsetter,getterを自動生成します。@synthesize プロパティ名 = 変数名
とすると、プロパティで使用する変数を明示的に指定することができます。
@implementationの中に記述します。
@synchronize
Javaのsynchronizeと同様、同期を行うためのものです。実際には、NSLockが利用されるようです。
#import
C/C++の#includeとほとんど同じですが、#ifndef AAA
#define AAA
#endif
のようなインクルードガードを書く必要がなくなります。
継承
@interfaceの継承は1つだけで、@protocolの継承は複数可能です。@interfaceの多重継承はできません。Java風味です。
ちなみに、@protocolの継承は、「プロトコルを採用する」とも言うようです。
オブジェクトの生成と破棄
基本は[クラス名 alloc]で生成、破棄は[オブジェクト release]で行います。オブジェクトは参照カウンタ方式で管理されています。
参照カウンタを増やす場合はretainです。
releaseを呼び出す度に参照カウンタが減ります。
0になったらオブジェクトが破棄されます。
コンストラクタ、デストラクタ
厳密に同じではありませんが、init, deallocは役どころが大体似ています。
initに引数が必要な場合は、自分でメソッドを宣言します。
その場合、習慣的に、initWith○○というメソッド名が用いられます。
initは、
[ [クラス名 alloc] init]
のように、大抵allocと同時に呼び出されます。
new、というものもあるのですが、使わない方がいいでしょう。
アクセス指定子
変数には、@private, @protectedというように指定できます。メソッドには適用できません。メソッドは基本的に全てpublicです。
Objective-Cのメソッドは、外から全く見えていなくても、
存在さえしていれば呼び出しが可能です。
とはいえ、ヘッダ部分に外から呼び出して欲しくないメソッドを書くのは可読性を下げますので、
その場合は無名カテゴリを使うと良いでしょう。
クラスメソッド
-(void)foobar
のように、先頭がハイフン(-)だとインスタンスメソッドですが、
+(void)foobar
のように、先頭をプラス(+)にすると、クラスメソッドになります。
this(自己参照)
selfです。ドット構文
プロトコルは、ドット構文で呼び出すことができます。@property (assign) int width;
というプロトコルを宣言しているならば、
self.width = 10;
ならば、widthのsetterを呼び出し、
int w = self.width;
ならば、widthのgetterを呼び出します。
実態は、[self setWidth:10], [self getWidth]と全く同じです。
いわゆるシンタックスシュガーです。
無名関数 (ブロック構文)
^(変数){...
}
といった形式で、無名関数を作ることができます。
JavaScriptの無名関数のようにバリバリ使われることは稀です。
大体GCD(Global Central Dispatch)か、アニメーションの定義で使われることがほとんどかと思います。
template
vectorただし、メタプログラミング的な機能はあります。
ありますが、私は使ったことがありません。
なんかやたらマニアックです。
まあ、template自体も大概マニアックですが。
以下2つはObjective-C独自。
カテゴリ
@interface クラス名 (カテゴリ名)のように、インタフェース宣言の後ろに括弧付きで宣言することで、
インタフェースのメソッドを拡張できます。変数の追加はできません。
カテゴリ名は無名でも可能です。
無名カテゴリは外部に公開したくないメソッドを宣言するのに利用できます。
その場合、カテゴリ宣言を.mファイル内に記述します。
他言語で一番似ているのはJavaScriptのprototypeでしょうか。
自動解放プール
オブジェクトに対してautoreleaseを呼び出すと、そのオブジェクトは自動解放プールに投げ込まれます。
自動解放プールは、一時オブジェクトのゴミ箱みたいなもので、
NSAutoreleasePoolというオブジェクトが管理しています。
ただし、GCのようにタイミングを見計らって掃除をしてくれるのではなく、
自分でゴミ箱を空にする必要があります。
あくまでも、解放タイミングを遅らせるためのものです。
@selector
@selector(メソッド)というように使います。@selector()はSEL型を返します。
SEL型は関数ポインタの亜種みたいなものです。
関数ポインタは型が完全一致していないとコンパイルエラーがでますが、
それに比べるとSEL型は緩いです。
ちなみにリフレクションをするときにはSEL型を使います。
@"文字列"
NSString用の文字列リテラルを生成します。前方宣言
@class interface名
です。前方宣言とは、importを使わずに、クラス(interface)型名だけを宣言するものです。
C++を書いてないとほとんど見かけることはないかと思いますが、
循環参照の問題を解決したり、コンパイル速度を向上させたり、
クラス間の関係を疎にしたりすることのできる、とても重要なイディオムです。
詳しい説明は、・・・検索してください。