woshidan's blog

あいとゆうきとITと、とっておきの話。

Objective-Cのクラス変数について

C言語Objective-Cでstatic修飾子をつけて変数を宣言したときの挙動

Javaを書いてからObjective-Cのコードを見ると驚くのですが、Objective-Cの元となっているC言語、およびObjective-Cでは関数やメソッド*1の中で有効であり、特にそう書いてない場合は初期化され直さずに存在し続けます。

// test.c
int countUp(void) {
  static int count;
  count++:
}

int main(void) {
  countUp();
  countUp();
  countUp();
}
// countUpが呼び出されるたびにcountの値が増えていく。

こうして定義された関数/メソッド内のローカル変数は、プログラムの実行開始から終了まで存在し続ける変数となります。Javaのクラス変数がクラスの初呼び出し時に定義されることと比べると不思議な感じがしますね。

Objective-Cのクラス変数をどう表現するか

ところで、Objective-Cには、クラスオブジェクトに付随する変数、いわゆるクラス変数を表現するための構文上の仕組みがありません。

さて、先ほど関数/メソッド内のstatic 修飾子をつけて宣言した変数の話をしましたが、関数/メソッド外で宣言した場合はどうなるのでしょうか。

C言語では、関数、および関数の外部で定義された変数は、自動的にプログラム全体で共有されコード上のどこからでも参照できるようになります。これにstatic指定子をつけると、自身が定義されたソースファイル上とヘッダファイルで存在を教えたソースファイル上に参照範囲を限定できます。

Objective-Cでも同様の振る舞いをするため、関数/メソッドの外部で定義された static 修飾子をつけて宣言した変数をクラス変数の代わりとして利用します。

static 修飾子をつけてメソッド外部で宣言した変数は、そのままだとJavaでいうprivate修飾子をつけて宣言したクラス変数と似たような働きをし、そのクラスのクラスメソッドとインスタンスメソッドから参照できるようになります。

ただし、この方法で定義されたクラス変数は、サブクラスに継承されません。このため、サブクラスでクラス変数を扱いたい場合は、スーパークラスでアクセサメソッドを定義して、それを継承させるようにします。

参考

C言語のstatic指定子について

Objective-C Mac OS Xプログラミング

Objective-C Mac OS Xプログラミング

苦しんで覚えるC言語

苦しんで覚えるC言語

*1:Objective-Cでは、関数の記法、呼び出し方によって、C言語の関数とObjective-Cオブジェクトのメソッドに分けられ、C言語のようにfuncName(arg1, arg2)で呼び出すものを関数、[Obj funcName:arg1 WithArg:arg2]で呼び出すものをメソッドと言います。ランタイムでコードブロックの管理するときの扱いも若干異なるみたいです