メソッドとプロパティの境界が曖昧【Objective-Cの良い所 その3】

Objective-Cの面白いところはメソッドとプロパティに等価関係がある所です。 引数なしのメソッドはプロパティとして振る舞うことも出来れば、その逆も可能です。

メソッド

-(int)intValue { return 99; }

// 普通のメソッド呼び出し
[self intValue]; // 99
// メソッドだがプロパティとして呼び出すことも可能
self.intValue;   // 99

プロパティ

@property double doubleValue;

// 普通のプロパティ呼び出し
self.doubleValue = 88;
self.doubleValue; // 88
// プロパティだがメソッドとして呼び出すことも可能
[self setDoubleValue:77];
[self doubleValue]; // 77

Objective-Cのプロパティはアクセサメソッド(ゲッターメソッド/セッターメソッド)をきちんと自動生成してくれているわけです。

ちなみに「self.doubleValue = 88」というプロパティ記法は、コンパイル時には「[self setDouble:88]」として解釈されます(なるほど〜)。

標準ライブラリでも有効

これはFoundation KitやCocoaフレームワークでも有効な仕様ですので、既存のメソッド呼び出しをプロパティ呼び出しに書き換えることも可能です。

// Before
[@"abc" length]; // 3
// After
@"abc".length;   // 3

もっとも、最近のバージョンのフレームワークでは、ほとんどの引数なしメソッドが呼び出し専用プロパティとして書き換えられているため、この仕様を意識的に活用する機会はもうほとんどないかもしれません。

ただ、今でもクラス・メソッドに関してだけは、この仕様が役に立つ場面があります。

// Before
[[NSUserDefaults standardUserDefaults] stringForKey:@""];
// After
[NSUserDefaults.standardUserDefaults stringForKey:@""];

このようにネストされた括弧[[]]を減らすことが出来ますので、コードの可読性を高める有効なテクニックにもなります。

デメリット

プロパティをメソッドとして呼び出す点については全く問題はありませんが、メソッドをプロパティとして呼び出す際には少しばかりの注意が必要です。Xcodeによる入力補完が効かないためです。エディタ上でNSUserDefaults.と入力しても、Xcodeはその先のstandardUserDefaultsをサジェストしてくれません。逆に従来メッセージ式で[NSUserDefaults と入力した場合には、きちんとメソッド名をサジェストしてくれます。

この辺の問題と対応についてはダークサイド Objective-C コーディング規約というシリーズでも解説しています。


私「メソッドとプロパティ周りの仕様だけは評価に値します」
Objective-C(うわ、なんか面倒くさいのが来た・・・)

広告
広告