プロパティとインスタンス変数の違いが良くわからなかったので調べてみた。
インスタンス変数
インスタンス変数はそのクラスから生成されたインスタンスオブジェクトが生きている限りは保持されるインスタンス固有の変数。
プロパティはそのインスタンス変数にアクセス指定子を付けて宣言することで、インスタンス自身ではないオブジェクトからもアクセスできるようになる。
インスタンス変数にはアクセス指定子を付けてアクセスを制御できる。
- @private
- @protected
- @public //デフォルト
- 例:@private uint age;
->でインスタンス変数にアクセスできる。
ただしアクセス指定子をつけても警告のみでアクセスできてしまうし、ビルドも通る…。ェ…。
Objective-Cにおけるプロパティはどんな機能を持っているのか?
* アクセサメソッドが自動的に作られる
Objective-Cのプロパティを実装するにはどうしたらいいか?
.hファイル側で
- @property(retain) NSString* propertyName;
#import @interface PropertyCheck : NSObject @property (retain) NSString* name; @end
.mファイル側で
- 通常はこう記述する。
- @synthesize propertyName;
- インスタンス変数名とプロパティ名が違う場合は以下の様にする。(※インスタンス変数が”_propertyName”の場合)
-
- @synthesize propertyName = _propertyName;
#import "PropertyCheck.h" @implementation PropertyCheck{ // NSString* name; } - (id)init{ self = [super init]; self.name = @"default"; return self; } @synthesize name; @end
ただし!
- @dynamic propertyName で宣言するとアクセサメソッドは生成されない。
- @dynamic propertyName で宣言するとコンパイル時にチェックされない。エラー、ワーニング等がでない。
生成されたアクセサメソッドの構文はドット表記で行うが良い。
PropertyCheck* propChck = [[[PropertyCheck alloc]init]autorelease]; NSLog(@"prop.name = %@",propChck.name); propChck.name = @"iPhone3GS"; NSString* name = propChck.name; NSLog(@"name = %@",name); NSLog(@"prop.name = %@",propChck.name); propChck.name = @"iPhone4S"; name = propChck.name; NSLog(@"name = %@",name);
これでログ側には
prop.name = default name = iPhone3GS prop.name = iPhone3GS name = iPhone4S
と表示されるはず。
ドット演算子の利点
通常の表記だとコンパイル時にチェックされないので実行するまでメソッド名が正しいかとか、存在するか等がわからない。
しかしドット演算子を使用すると使用可否がコンパイル時にチェックされる。
アクセサメソッドに任意の名前を付ける
アクセサメソッド名を自作するには以下の様に表記を変更する。
@property (getter=nowHealthPoint, setter=damagedHealthPoint:) NSInt enabled;
getterは引数無しだがsetterは引数ありなので必ずセミコロンを記述しておく。
同じ変数にアクセスするのでgetterの返り値の型とsetterの引数の型は一致する。この例ではNSIntにしてある。
プロパティの属性
- readwrite
- 読み書き可だよ。
- readonly
- 読み込みのみだよ。setterが生成されなくなる。
- retain
- 新規参照。参照数をインクリメント。
- ガービッジコレクションを有効にしてるとretainは無効になる。
- ガービッジコレクションを無効にしている場合、手動でreleaseする必要がある。
- assign
- まま渡される。
- ガービッジコレクションが無効だと警告の上、これが適用される。
- copy
- set時にコピーが渡される。
- ガービッジコレクションを無効にしている場合、手動でreleaseする必要がある。
プロパティとインスタンス変数
インスタンス変数として宣言するならプロパティとして定義した方が良いという結論に。
歴史ある言語って色々便利な分だけ分かりにくいね…。等など。