2013年9月11日水曜日

Objective-C勉強(9);メンバーの公開範囲



メンバーの公開範囲



通常、クラスメンバー変数はそのメソッドによってのみアクセスされるべきである。
が、メソッドの呼び出しはCの関数呼び出しに比べ(出来ることが多い分)遅いので、
高速性を求められるプログラムではメンバー変数に直アクセスアクセスする必要があるかもしれない。


しかし、全メンバーを公開してしまうと、いじられたくない部分までいじられる可能性がある(特に派生クラスを作る時)ので、公開範囲を限定できる。


@public 全公開(外部、このクラス内、子クラス内)
@private このクラス内のみ公開
@protected このクラスおよび子クラス内のみ公開;デフォルト


これを記述した後のメンバー変数は全てその公開範囲となる。クラス定義内で何回、どの順序で書いても良い。
クラスの属性値は@publicに、内部変数は@privateまたは@protectedにするといいのだろう。
C言語で言うなら、グローバル変数、ファイル内static変数、auto変数と考えるとわかりやすい。

Apple純正のObjective-C解説

によると
@publicの利用は避けるべき

と書かれている。
デバッグ時に内容読むのには使えると思うけどね(デバッグ中だけ@publicにしておく)。


ついでに書くと、クラスをidで受けてしまうとメンバー変数がコンパイル時には不定でエラーになるので、「クラス名 *」で定義する必要がある。
@interface A : NSObject
{
@public
    int a;
@protected
    int b;
@private
    int c;
}
- (id)initWithA:(int)a arg2:(int)b arg3:(int)c;
- (void)WriteA;
@end

@interface B : A
// 変数がないので{}は省略
- (void)WriteB;
@end

@implementation A
- (id)initWithA:(int)a arg2:(int)b arg3:(int)c
{
    self->a = a;  // @publicメンバーへの代入はポインタを経由して行う
    self->b = b;
    self->c = c;
    return(self);
}
- (void)WriteA
{
    printf("[A Write a=%d, b=%d, c=%d]\n", a , b , c);
}
@end

@implementation B
- (void)WriteB
{
    printf("[B Write a=%d, b=%d]\n", a , b); // cにはアクセスできない
}
@end

int main()
{
    B * objb = [[B new] initWithA:1000 arg2:100 arg3:10];
    printf("[main() a=%d]\n" , objb->a); // @publicなのでメンバー変数に直接アクセスできる
    objb->a=200; // 当然代入も出来る
    [objb WriteB];
    [objb WriteA];
    [objb ObjFree];
    return(0);
}
このあたりはCで書いてた構造体を持つライブラリを移植していくと理解が深まるのであろう。

Objective-C V2.0で導入されたプロパティを使うと自動的にアクセスメソッドを生成させることが出来るので、この公開範囲をいじるというのは「高速化を除き」今後余り行わない方が良いのかもしれない。


世間に公開するようなライブラリを作るならいざ知らず、個人の開発においてはほぼ無用であろう。
私は一度も使ったことがない。

0 件のコメント:

コメントを投稿