可視性


インスタンス変数の公開範囲

通常、クラスは構造体とは異なる役割があるため、データ型の提供としてのクラスというものは存在するべきではありません。 しかし、RGB 形式の色を表現するためのクラスや、座標やサイズを表すクラスであれば、メッセージから値を得るという処理はやや冗長なので、直接インスタンス変数とやり取りできたほうが良いと考える開発者もいるでしょう。

原則としては、クラスのインスタンス変数に外部からアクセス可能であるべきではありませんし、デフォルトでは外からインスタンス変数にアクセスすることは出来ません。 基本的に、インスタンス変数を宣言するクラスのメソッド以外からインスタンス変数を操作されると、変数に保存されている値の整合性を保てなくなるためです。 外部からインスタンス変数にアクセスするには、まず、インスタンス変数の可視性を明確にしなければなりません。

インスタンス変数の可視性は、公開を表す public、非公開を表す private、サブクラスからのアクセスを許可する protected に分かれます。 public は、クラスの外部やサブクラスを含め、あらゆる場所からインスタンスを通してアクセスされる変数を表します。 private は、逆にインスタンス変数を宣言したクラスのメソッドからのみアクセス可能な変数です。 そして、protected は変数を宣言したクラスと、そのクラスのサブクラスからアクセスできる変数を表します。

宣言するインスタンス変数にこれらの可視性を指定するには、コンパイラディレクティブを用いて @public@private@protected のいずれかを、インスタンス変数宣言部分の間に挿入します。 これらのコンパイラディレクティブが出現すると、それ以降に宣言されたインスタンス変数はすべて、指定された可視性に設定されます。 可視性が指定されていない場合、インスタンス変数は protected に設定されます。

@interface A : Object
{
	int z;	//protected
@public
	int a;	//public
@protected
	int b;	//protected
@private
	int c;	//private
	int d;	//private
}
@end

このように、可視性を指定した後に宣言されたインスタンス変数は、その可視性を持ちます。 可視性を指定するコンパイラディレクティブの出現順序、出現回数に制限はありません。

public な公開されている変数に、クラスの外部からインスタンスを通してアクセスするには、クラス型のポインタ変数から -> 演算子を使ってインスタンス変数を指定します。 これは、構造体へのポインタからメンバ変数にアクセスする方法と同じです。 インスタンス変数へのアクセスはコンパイル時に型チェックが必要となるため id 型の変数からアクセスすることは出来ません。

#import <stdio.h>
#import <objc/Object.h>

@interface A : Object
{
@public
	int a;
@protected
	int b;
@private
	int c;
}
- (id)initWithA:(int)a int:(int)b int:(int)c;
- (void)WriteA;
@end

@interface B : A
- (void)WriteB;
@end

@implementation A
- (id)initWithA:(int)a int:(int)b int:(int)c {
	self->a = a;
	self->b = b;
	self->c = c;
	return self;
}
- (void)WriteA {
	printf("[A Write Method, a=%d, b=%d, c=%d]\n", a , b , c);
}
@end

@implementation B
- (void)WriteB {
	printf("[B Write Method, a=%d, b=%d]\n", a , b);
}
@end

int main() {
	B * objb = [[B new] initWithA:1000 int:100 int:10];
	printf("[main() scope, a=%d]\n" , objb->a);
	[objb WriteB];
	[objb WriteA];
	[objb free];
	return 0;
}

このプログラムで宣言している A クラスは、public インスタンス変数 a、protected インスタンス変数 b、private インスタンス変数 c を宣言しています。 そして、これらにアクセスすることができることを証明するために、main() 関数から B 型のポインタ変数 objb を通して、公開されている変数 a に objc->a という形でアクセスしています。

A クラスを継承するサブクラス B では、WriteB というメソッドを宣言し、このメソッドの実装で公開されている変数 a と、サブクラスからのアクセスを許可されている変数 b を表示します。 ただし、サブクラスからも private な変数にアクセスすることはできないため c を表示することはできません。 すべての変数にアクセスできるのは、インスタンス変数を宣言する A クラスだけです。 A クラスのメソッド WriteA からは、すべてのインスタンス変数を表示することが可能です。



前のページへ戻る次のページへ