このちょっとした構文は、Objective-C で私を混乱させました。
myObject を呼び出すだけではなく、いつ self.myObject を呼び出す必要がありますか?
冗長に見えますが、交換可能ではありません。
誰かが私を啓発してくれませんか?
このちょっとした構文は、Objective-C で私を混乱させました。
myObject を呼び出すだけではなく、いつ self.myObject を呼び出す必要がありますか?
冗長に見えますが、交換可能ではありません。
誰かが私を啓発してくれませんか?
それらにアクセスするだけなら、 を使用する理由はあまりありませんself.member
。割り当てを行っている場合は、単純なパラメーター以上のことを行っているとよいでしょう。@property (assign)
たとえば、retain、copy などです。これにより、作成中のコードを節約できます。例:
myObject = anotherObject;
self.myObject = anotherObject;
2 番目の選択肢は、実際にオブジェクトを希望どおりに割り当てていることを確認します (コピーの取得、保持カウントの増加など)。と変わらない[self setMyObject:anotherObject]
。
ドット表記はコンパイラによってメッセージの代わりに使用されるため (通常の配列での become の動作と同様)、通常のメッセージに対してドット表記を使用しても、オーバーヘッドや余分な効率はありませんx[5]
。*(x + 5*sizeof(x))
Mark や Cinder6 に同意するとは言えません。
まぁ、前半は同意。:-)self.foo
メソッドを呼び出してい-foo
ます。Plainfoo
はfoo
ivar にアクセスしています。
ほとんどの状況では、常にメソッドを実行する必要があります。それらは、実際のストレージからあなたを抽象化し、必要になる可能性のある他の動作から遠ざけるためにそこにあります。後でクラスをサブクラス化するとどうなるか考えてみてください。ほとんどの場合、カバーする機能にアクセスする場所で、独自のパブリック メソッドを呼び出す必要があります。
例外は、オブジェクトの初期化とティアダウン、およびそれらを合成しない場合のプロパティ アクセサー自体です。オブジェクトの初期化とティアダウン中に、メソッドのサブクラス実装を呼び出したくありません。これらのメソッドは、部分的にセットアップされた状態のオブジェクトを処理する必要がないためです。
同じクラスの実装内からプロパティ アクセサーを呼び出すことはほとんどありません。クラスのインスタンス メソッドは内部状態に便利にアクセスできるため、通常はその状態に直接アクセスするのが理にかなっています。
合成されたアクセサーを使用している場合、それらを呼び出すと、(おそらく) 不必要なオーバーヘッドが追加されます。アクセサーの実装がより複雑な場合は、コードの目的をあいまいにするだけです。
最後に、Objective-C を初めて使用する一部の人々は、self.property 構文と合成アクセサーを使用して、Cocoa メモリ管理を理解する必要がないようにしています。それがどのように機能するかを実際に学ぶ必要があるため、それを避けようとすると逆効果になります.
If you're using Core Data, you should essentially always use the accessors, since some properties may not be loaded from the persistent store until needed. (Assuming you're using a SQLite store, anyway.)
If you're not using Core Data, you're generally safe to just use myObject
directly if you're only reading the value. If you're modifying the value of myObject
, you need to use the accessors in order to make sure that any other objects observing the value of that property are properly notified. In other words:
// Not changing the value of myObject, so no accessor needed
[someMutableArray addObject:myObject];
// Changes the value, so you need to use the accessor
self.myObject = newObject;
[self setMyObject:newObject]; // Exactly identical to the previous line.
In general, though, there's very little overhead; I prefer to always use the accessors, even within the same object. (Of course, there's the argument over using them in initializers, but that's a separate issue.)
切り干しの答えはありません。ただし、時期尚早の最適化は良くないことに注意してください。Mac または iPhone 上の Cocoa では、アクセサ/プロパティの使用は KVO 準拠である必要があります。Core Data および Cocoa バインディングが自動的に機能するには、KVO 準拠が必要です。Core Data では、プロパティを変更するときだけでなく、それらにアクセスするときにも KVO を確保する必要があります。
プロパティのメモリ管理動作を確実にしたい場合にも、アクセサー/プロパティを使用することをお勧めします。つまり、常に ivar を設定してセッターまたはドット表記を使用し、従うメモリ管理パターンに応じて、常に使用するivar を取得するときのアクセサー/プロパティ。
さまざまなメモリ管理パターンが多数あります。壊れていないものはすべて、アクセサーによって返されたオブジェクトが少なくとも現在の autorelease スコープの終わりまで存続することを保証します。つまり、オブジェクトが明示的に保持され、現在の自動解放スコープで自動解放されます。Apple が推奨する方法では、getter で明示的にこれを行います。
- (id)foo {return [[foo retain] autorelease]; }
- (void)setFoo:(id)aFoo {
if(! [aFoo isEqual:foo]) {
[foo release];
foo = [aFoo retain];
}
}
これは、合成されたアクセサーで従うパターンであることを暗示しています。個人的には、セッターで自動解放することを好みます。
- (id)foo {return foo;}
- (void)setFoo:(id)aFoo {
[foo autorelease];
foo = [aFoo retain];
}
これにより、新しい値に置き換える前に古い値が自動的に解放されます。これは、ゲッターでの保持と自動解放とまったく同じ効果がありますが、オブジェクトを自動解放プールに一度だけ追加する必要があります。ほとんどの場合、保持カウントは 1 であり、自動解放されないため、何が起こってもどこにも行きません。プロパティがまだ保持されているコード (デリゲート コールバックなど) でプロパティが置き換えられた場合、その下から消えることはありません。
これが意味することは、アクセサー/プロパティを使用すると、オブジェクトが必要な限り、コードの他の部分がオブジェクトを解放しなくても、オブジェクトが存在し続けるという確信が得られるということです。
アクセサー/プロパティを常に使用する最後の最良の理由は、各プロパティの仮定が 1 つ少なくなることです。つまり、そのプロパティの基礎となる ivar があり、それが同じ名前を持っていることです (2 つの仮定だと思います)。おそらく将来的には、ivar を派生アクセサーに置き換えたいと思うでしょう。プロパティ表記は引き続き機能します。おそらく、ivar の名前を変更したいと思うでしょう。プロパティは引き続き機能します。幸いなことに、Xcode でのリファクタリングは通常信頼できますが、わざわざ気にする必要はありません。
オブジェクト指向プログラミングのポイントは、クラスで定義されたインターフェースを使用することです。クラスが自身のインターフェースを無視する正当な理由はありません (ただし、偏見や合理化された理由はたくさんあります)。アクセサー自体を除くすべてのメソッドは、一般的に、オブジェクトを神聖なものとして扱い、その内部状態を非公開として扱う必要があります。すべてのメソッドをカテゴリまたはサブクラスにあるかのように記述し、ivar をプライベートな状態として扱います。ivar に直接アクセスする正当な理由はたくさんありますが、それらはケースバイケースで決定されます。