Objective-Cの @property と @synthesize の組み合わせが何をやっているのかを解説
改めて説明するまでも無いかと思ってたけど意外と知らない人は知らないみたいので解説を書いておきます。
@property と @synthesize の組み合わせは端的に言うと「setterとgetter(アクセッサメソッド)をコンパイルの前に生成させる」以上。
※Objective-Cの場合、 @ で始まるものはプログラムでは無く、コンパイラへの指示となります。この様な指示をObjective-Cではコンパイラディレクティブ(Compiler directive)と呼びます。
詳細説明
setterやgetterはメンバ変数を直接扱わずにメソッド経由で代入やデータの取得をする為に定義するメソッドです。setterがデータを代入する時のメソッド、getterがデータを取得する時のメソッドとなります。
メンバ変数をメソッド経由にすることにより代入前にチェックを行って有効な値のときのみメンバ変数に代入したり、そのメンバ変数の値が想定外の場合の値だった場合にその値が代入された箇所を簡単に特定でき、デバックが容易になったりする利点があります。
他の言語だと自分でそれぞれのメソッドを記述する必要が有ったりするものも有りますがObjective-Cでは @property と @synthesize を定義する事によりコンパイルの前にsetterやgetterのメソッドが追加されます。
例えば .h ファイルで以下の様に NSString *test_; とプロパティ宣言 @property (nonatomic, retain) IBOutlet NSString *test; が記述されていて
@interface TestAppDelegate : NSObject <UIApplicationDelegate> { UIWindow *window; TestViewController *viewController; NSString *test_; } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) IBOutlet TestViewController *viewController; @property (nonatomic, retain) IBOutlet NSString *test;
.m ファイルで以下の様に @synthesize が記述されていると
@synthesize test=test_;
以下の様なメソッドが自動的に追加されます。
※メソッドの内容は予想です。しかし、恐らくこれに近い内容だと思われます。
- (NSString*)test { return test_; } - (void)setTest:(NSString*)newTest { if (test_ != newTest) { [test_ release]; test_ = [newTest retain]; } }
setter、getterが追加されている事を確認
setter、getterが追加されている事は以下の様なプログラムを作成し、 @synthesize test=test_; にブレークポイントを設定して実行すると確認出来ます。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.test = @"test"; NSLog(@"%@ word.", self.test); // Add the view controller's view to the window and display. [window addSubview:viewController.view]; [window makeKeyAndVisible]; return YES; }
self.test = @"test";
スタックトレースを確認すると [TestAppDelegate application:didFinishLaunchingWithOptions:] から [TestAppDelegate setTest:] が呼ばれているのが確認できるかと思います。
同様に以下の部分で止まった時に
NSLog(@"%@ word.", self.test);
スタックトレースを確認すると [TestAppDelegate application:didFinishLaunchingWithOptions:] から [TestAppDelegate test] が呼ばれているのが確認できるかと思います。
ちなみに以下の様な記述に変えるとプロパティ呼び出しでは無く、インスタンス変数へのアクセスとなるためブレークポイントで止まる事は無くなります。
NSLog(@"%@ word.", test_);
もちろん、同様に以下の記述でも止まりません。
NSLog(@"%@ word.", self->test_);
デフォルトのsetter、getterの定義を自分で実装する
コンパイラが作成するはずのsetter、getterと同じメソッド名のメソッドを記述する自分で実装を記述する事が可能です。以下の様に記述するとプロパティ(test)にアクセスした時にここで記述したメソッドが呼ばれます。
- (NSString*)testData { NSLog(@"testData"); return test_; } - (void)setTestData:(NSString*)newTest { NSLog(@"setTestData"); test_ = newTest; }
setter、getterのメソッド名を自分の指定した名称にする。
ちなみに自身でsetter、getter定義する場合の名称は自分で指定する事も出来ます。
その場合、.h ファイルで以下の様にpropertyを宣言し、
@property (nonatomic, retain, setter=setTestData, getter=testData) IBOutlet NSString *test;
.m ファイルに以下の様にsetter、getterを記述します。
- (NSString*)testData { NSLog(@"testData"); return test_; } - (void)setTestData:(NSString*)newTest { NSLog(@"setTestData"); test_ = newTest; }
今回のサンプルはこちらからDL出来ます。
関連サイト
Apple公式の日本語ドキュメントの「Objective-C 2.0 プログラミング言語」
iOS Reference Library
http://developer.apple.com/jp/devcenter/ios/library/japanese.html
Objective-C 2.0プログラミング言語: プロパティの宣言と実装
http://developer.apple.com/jp/documentation/cocoa/conceptual/objectivec/Articles/chapter_5_section_3.html#//apple_ref/doc/uid/TP30001163-CH17-SW12
- 作者: 荻原剛志
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2008/05/28
- メディア: 大型本
- 購入: 52人 クリック: 603回
- この商品を含むブログ (146件) を見る
- 作者: 木下誠
- 出版社/メーカー: ビー・エヌ・エヌ新社
- 発売日: 2009/03/27
- メディア: 単行本(ソフトカバー)
- 購入: 9人 クリック: 119回
- この商品を含むブログ (30件) を見る