getterとsetterとは
まずは簡単な例として@propertyで外部から読み書きともにアクセス可能な変数について考えてみます。 外部からオブジェクト内の変数などへアクセスする場合、たとえばオブジェクト外部においてmyObjectという名前で宣言したオブジェクトにある、 myValueという名前の変数なら、 myObject.myValueと書いたものを式の右辺におけば現在の値を取り出せます。逆に左辺におけば外部から値を変更することが出来ます。 このときオブジェクトの内部ではゲッターやセッターと呼ばれるものが働いています。例えば先ほどのmyValueがNSInteger型の変数だとすると、 値を入手する場合には
- (NSInteger)myValue {
return myValue;
}
に相当するようなメソッドが実行されています。これをゲッター(getter)と呼びます。逆に値を変更する場合には
- (void)setMyValue:(NSInteger)anInteger {
myValue = anInteger;
}
に相当するようなメソッドが実行されています。これをセッター(setter)と呼びます。セッターとゲッターは一組で外とのデータの受け渡しを行いますが、 同じ名前だと問題があるため、セッター側にはsetを前に付けたメソッド名を使います。基本的な命名規則ではsetが付くことで初めのmがMに変更されます。
@synthesizeの使い方
さて、ここまででゲッターとセッターの役割について説明してきましたが、プログラミングを行う側としては、変数を作るたびにこのような決まりきった動作をさせるだけのゲッターやセッターを作るのは面倒です。 そのため、テンプレート的な動作をさせるだけの、特殊な動作を含まないゲッターやセッターは自動的に生成されるほうが楽です。 そのときに使うのが@synthesizeです。上の例の場合だと、ヘッダファイルに
@property (nonatomic, assign) NSInteger myValue;
と書いてあれば、メソッドファイルの@implementationが終わった次の行に
@synthesize myValue;
と書いておくだけで、上で示したようなゲッターやセッターをビルド時に自動で追加してくれます。 別の種類のオブジェクトなどで他のプロパティのオプションを選んだときにも適切なゲッターやセッターを追加してくれるのでとても便利です。
セッターを使った小技
@synthesizeマクロを使えば自動的にゲッターやセッターが作られますが、自前でセッターを作ってしまうこともできます。 例えばその変数の値を外部から変更した時に、同時にしなければならない処理があるなら、セッターを作り、そこにその処理を書いてしまう方法もあります。 わかりやすい単純な例を以下に示します。上のmyObjectにNSInteger型の別の変数myValue2もあるとします。 myValue2はプロパティを設定しておらず外部から直接値を変更できないようになっているものとしましょう。
- (void)setMyValue:(NSInteger)anInteger {
myValue = anInteger;
myValue2 = anInteger * 2;
}
この場合、myObjectをインポート済みの外部のオブジェクトからmyValueを変更するだけで、 同じオブジェクト内で宣言済みのmyValue2というNSInteger型の変数にmyValueの2倍の値が勝手に入ります。 ちなみにこのような状態でmyObject内部で
myValue = 2;
と書かれている場合には、ただ単にmyValueの値が2になるだけですが、
self.myValue = 2;
と書いた場合には、内部からでもセッターが呼び出されるためmyValue2の値が4になります。 当然ながらself.を付けてこのように書けるのは外部から変更可能なようにプロパティが設定されているものだけなので、
@property (nonatomic, readonly) NSInteger myValue;
のような読み出し専用プロパティが設定されていたり、そもそもプロパティ設定が無い場合はエラーが発生します。
なお以下のように書いてしまうと永久に抜け出せないループになってしまいますので気をつけましょう。
- (void)setMyValue:(NSInteger)anInteger {
self.myValue = anInteger; // セッターからさらにセッターが呼ばれループしてしまいます。
}
前へ次へ