Apple Developer Connection
Advanced Search
Member Login Log In | Not a Member? Contact ADC

< 前ページ次ページ >

ドット構文

Objective-Cには、プロパティへの読み取り/書き込みアクセス許可を与えるドット(.)演算子があります。プロパティpropertyの読み取りとは、そのプロパティのgetterメソッド(デフォルトではproperty)を呼び出すことであり、書き込みとはそのプロパティのsetterメソッド(デフォルトではsetProperty:)を呼び出すことです。

このセクションの内容:

概要
nil値
self
パフォーマンスとスレッド
使用方法のまとめ
適切でない使用方法のまとめ


概要

ドット(.)演算子を使ってプロパティにアクセスできます。プロパティ式は、標準のキー値コーディング準拠のメッセージ送信として実装されます。つまりプロパティpropertyの読み取りは、当該プロパティのgetterメソッド(デフォルトではproperty)の呼び出しであり、書き込みは当該プロパティのsetterメソッド(デフォルトではsetProperty:)の呼び出しです。したがって、宣言されたプロパティはカプセル化は守られます。つまり、宣言されたプロパティを使っているときは、インスタンス変数に直接にはアクセスしているように見えますが、そうではありません。ドット演算子を使って、さらに柔軟性のある使用パターンが可能になりますが、それらは使用しないことを強くお勧めします。

プロパティ式は機能的にはメッセージ送信と同じですが、コンパイラは読み取り専用プロパティへの書き込みを検出するとエラーを送信できるのに対し、存在しないsetProperty:メソッドを呼び出した場合は(実行時に失敗します)未宣言メソッドの警告を生成できるだけです。

次の例は、プロパティとドット構文の使い方を示しています。

リスト 4-5  ドット構文を使ったプロパティへのアクセス

Graphic *graphic = [[Graphic alloc] init];
 
NSColor *color = graphic.color;
CGFloat xLoc = graphic.xLoc;
BOOL hidden = graphic.hidden;
int textCharacterLength = graphic.text.length;
 
if (graphic.textHidden != YES)
{
    graphic.text = @"Hello";
}
graphic.bounds = NSMakeRect(10.0, 10.0, 20.0, 120.0);

次の文は、リスト 4-5のコードと同等ですが、ここではカスタムアクセサメソッド(自分自身で実装したもの、または合成されたもの)を使用しています。

リスト 4-6  アクセスメソッドを使ったプロパティへのアクセス

Graphic *graphic = [[Graphic alloc] init];
 
NSColor *color = [graphic color];
CGFloat xLoc = [graphic xLoc];
BOOL hidden = [graphic hidden];
int textCharacterLength = [[graphic text] length];
 
if ([graphic isTextHidden] != YES)
{
    [graphic setText:@"Hello"];
}
[graphic setBounds:NSMakeRect(10.0, 10.0, 20.0, 120.0)];

プロパティとキー値コーディングを使うこともできます。詳しくはプロパティとキー値コーディングを参照してください。

適切なC言語タイプのプロパティの場合、複合代入の意味は明確です。たとえば、次の複合代入を使って、NSMutableDataのインスタンスの長さプロパティを更新できます。

NSMutableData *data = [NSMutableData dataWithLength:1024];
data.length += 1024;
data.length *= 2;
data.length /= 4;

次のように記述しても同じです。

[data setLength:[data length] + 1024];
[data setLength:[data length] * 2];
[data setLength:[data length] / 4];

プロパティを使用できないケースが1つあります。次のコードを考えてみましょう。

id y;
x = y.z;  // zは宣言されていないプロパティ

yは型なしであり、zプロパテは宣言されていません。これは何通りかの解釈ができます。曖昧であるため、この文は未宣言のプロパティエラーとして扱われます。zが宣言されている場合、現在のコンパイル単位の中にzプロパティの宣言が1つだけあれば、コードは曖昧ではなくなります。zプロパティの宣言が複数ある場合は、それらすべてが同じ型(BOOLなど)であればコードは正当です。曖昧さの原因となり得ることの1つはまた、プロパティの1つがreadonlyと宣言されていることです。

nil値

プロパティの渡り歩きの間にnil値が見つかった場合、結果は同等のメッセージをnilに送った場合と同じです。たとえば、次の組み合わせはすべて同じです。

// パスの各メンバはオブジェクト
x = person.address.street.name;
x = [[[person address] street] name];
 
// パスにはCの構造体が含まれおり、
// ウインドウがnilの場合、または-contentViewがnilを返した場合はクラッシュする
y = window.contentView.bounds.origin.y;
y = [[window contentView] bounds].origin.y;
 
// setterの使用例....
person.address.street.name = @"Oxford Road";
[[[person address] street] setName: @"Oxford Road"];

self

アクセサメソッドを使ってselfのプロパティにアクセスする場合は、次の例に示すようにselfを明示的に呼び出す必要があります。

self.age = 10;

self.を使用しない場合は、インスタンス変数に直接アクセスします。次の例では、ageプロパティのsetアクセサメソッドは呼び出されません

age = 10;

パフォーマンスとスレッド

ドット構文では、標準的なメソッド呼び出し構文に相当するコードが生成されます。結果として、ドット構文を使ったコードは、アクセサメソッドを使って直接記述したコードとまったく同じように実行します。ドット構文はメソッドを単に呼び出すだけであるため、使用した結果、スレッドの依存性がさらに発生することはありません。

使用方法のまとめ

aVariable = anObject.aProperty;

aPropertyメソッドを呼び出し、戻り値をaVariableに代入します。プロパティaPropertyの型とaVariableの型は互換性がなくてはなりません。互換性がないとコンパイラ警告が生じます。

anObject.name = @"New Name";

setName:メソッドをanObjectに対して呼び出し、引数として@"New Name"を渡します。

setName:が存在しないかプロパティnameが存在しない場合、あるいはsetName:void以外を返した場合はコンパイラ警告が生じます。

xOrigin = aView.bounds.origin.x;

boundsメソッドを呼び出し、xOriginboundsから返されたNSRectorigin.x構造体の値になるように代入します。

NSInteger i = 10;
anObject.intProperty = anotherObject.floatProperty = ++i;

anObject.intPropertyanotherObject.floatPropertyの両方に11を代入します。つまり代入の右辺が先に評価され、結果がsetIntProperty:setFloatProperty:に渡されるということです。先に評価された結果は、代入の各ポイントで必要に応じて変換されます。

適切でない使用方法のまとめ

以下に示すパターンの使用は勧められません。

anObject.retain;

コンパイラ警告が生じます(warning: value returned from property not used.)。

/* メソッド宣言 */
- (BOOL) setFooIfYouCan: (MyClass *)newFoo;
 
/* コード */
anObject.fooIfYouCan = myInstance;

setFooIfYouCan:は、(void)を返さないためsetterメソッドであるように見えないことを示すコンパイラ警告が生じます。

flag = aView.lockFocusIfCanDraw;

lockFocusIfCanDrawを呼び出し、値をflagに代入します。この場合、flagの型がメソッドの戻り値の型と不一致でない限り、コンパイラ警告は生じません。

/* プロパティ宣言 */
@property(readonly) NSInteger readonlyProperty;
/* メソッド宣言 */
- (void) setReadonlyProperty: (NSInteger)newValue;
 
/* コード */
self.readonlyProperty = 5;

プロパティがreadonlyとして宣言されているため、このコードではコンパイラ警告が生じます(warning: assignment to readonly property 'readonlyProperty')。実行時には動作しますが、プロパティに対してsetterを単に追加してもreadwriteの意味を持たせることはできません。



< 前ページ次ページ >


Last updated: 2007-10-31




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice