sandbox

Scala, Android, Architecture, Management, Service Design あたりを主戦場としております

Objective-C 2.0 プログラミング言語を読む #2

引き続き読みます。
あと 100 ページくらい。。今日で読み終えたい!

ソースファイル

Objective-C ではインターフェースを定義するファイルと、実装を記述するファイルを分ける。
インターフェースを定義するファイルは .h、実装を定義するファイルは .m の拡張子とする。

この為、通常は2つのファイルに分けられることになるが、カテゴリを使用する場合は複数のファイルになることもある。

クラスインターフェース

クラスインターフェースの宣言

@interface SampleClass:SuperSampleClass
{
  //instance variable declarations
  float width;
  BOOL filled;
  NSColor *fillColor;
}
//method declarations
+ alloc; //+ クラスメソッド
- (void) display; //- インスタンスメソッド
- (void) setRedius:(float)aRadius;
@end

Java 的な感覚だと、スーパクラス名を省略しても NSObject を継承してくれるのかと思ってしまうが、
実際には NSObject のライバル、つまり新しいルートクラスとして定義される。

メソッド名、変数名について

一般的ではないが、クラスメソッドとインスタンスメソッドは同じ名前で定義することも出来る。
メソッドとインスタンス変数も同じ名前で定義することが出来、一般的にアクセッサで使用される。

- (float) radius; //getter (インスタンス変数名と同じ)
- (void) setRadius:(float)aRadius; //setter

ちなみに、上記の alloc の様に戻り型や引数型を指定しないと、id 型と見なされる。

複数の引数を持つメソッド

複数の引数をメソッドの場合は、コロンの後に引数を宣言する。

- (void) setWidth:(float)width height:(float)height;
// ややこしいけど、メソッド名:(引数1)変数名 ラベル:(引数2)変数名 という形
可変長引数のメソッド

可変長引数を持つメソッドの場合は、コンマと省略記号を使用して宣言する。

- makeGroup:group, ...;
インターフェースのインポート

Objective-C では include ではなく、 import を使用する。

#import "Rectangle.h"

import は同じファイルが2回以上インクルードされないことが保証されている。

他のクラスの参照

インターフェースファイルで、インターフェース詳細に依存しない場合は @class ディレクティブを用いる。
そして、実装ファイルの方で実際にインターフェースをインポートする。

@class Rectangle, Circle;

クラス実装

@implementation ディレクティブで始まり、@end ディレクティブで終わる。

#import "SampleClass.h" //自身のインターフェースをインポート

@implementation SampleClass //スーパークラス名は省略出来る
{
  //インスタンス変数宣言は省略出来る
}
//メソッド実装だけ定義する
+ alloc 
{
  ...
}

- (void) setFilled:(BOOL)flag
{
  ...
}
...
インスタンス変数の参照

インスタンスメソッドは、名前だけでインスタンス変数を参照することが出来る。

- (void) setFilled:(BOOL)flag
{
  filled = flag;
}

インスタンス変数がレシーバでないオブジェクトに属する時は、オブジェクトの型を静的な型定義によってコンパイラに明示しなければならない。
この場合は、構造体ポインタ演算子(->)を使用する。

- makeIdenticalTwin
{
  if (!twin) {
    twin = [[Sibling alloc] init];
    twin->gender = gender;
    twin->appearance = appearance;
  }
  return twin;
}
インスタンス変数の有効範囲
ディレクティブ 意味
@private クラス内のみ
@protected クラス内、継承するクラス内(これがデフォルト)
@public どこからでも
@package クラスを実装するイメージ内では @public の様に振舞い、外側では @private の様に振る舞う。

@package の説明が抽象的でいまいち良くわからないなぁ。イメージ内ってなにさ。
他に詳しく説明された資料はないだろうか。。