1. ホーム
  2. objective-c

[解決済み] なぜアイバーを使うのですか?

2022-04-28 18:14:19

質問

この質問は、通常、次のような逆質問を目にします。 すべてのivarはpropertyでなければならないのか? (このQに対するbbumさんの回答が好きです)。

私は自分のコードではほとんどプロパティしか使いません。 しかし時々、長い間iOSで開発を続けてきた、伝統的なゲームプログラマーである契約社員と仕事をすることがあります。 彼は、ほとんど何のプロパティも宣言せず、ivarに依存したコードを書いています。 1.) Objective C 2.0 (Oct '07)までプロパティが常に存在したわけではないので、それに慣れているから、2.) ゲッター/セッターを経由しないことによる最低限のパフォーマンス向上のため、と私は推測しています。

彼はリークしないコードを書いていますが、私はまだ彼がivarよりもプロパティを使うことを希望しています。 私たちはそのことについて話しましたが、彼はKVOを使用しておらず、メモリの問題に対処した経験があるため、プロパティを使用する理由はないと考えているようです。

それよりも質問なんですが...。 経験者であろうとなかろうと、なぜivarを使おうと思ったのでしょうか。 アイバーを使うことが正当化されるほど、本当に大きな性能差があるのでしょうか?

また、明確にするポイントとして、私は必要に応じてセッターとゲッターをオーバーライドし、ゲッター/セッターの内部でそのプロパティに関連するivarを使用します。 しかし、ゲッター/セッターやinitの外では、私は常に self.myProperty の構文があります。


編集1

良いご回答ばかりで、感謝しています。 1つだけ、間違っていると思われる点を指摘すると、ivarではカプセル化されますが、propertyではそうではありません。 クラスの継続でプロパティを定義すればいいのです。 これによって、外部の人間からそのプロパティを隠すことができます。 また、インターフェイスでプロパティをreadonlyと宣言し、実装でreadwriteと再定義することも可能です。

// readonly for outsiders
@property (nonatomic, copy, readonly) NSString * name;

で、クラス継続で持っています。

// readwrite within this file
@property (nonatomic, copy) NSString * name;

完全にプライベートなものにするには、クラスの継続で宣言するだけです。

どのように解決するのですか?

カプセル化

ivarがprivateだと、プログラムの他の部分は簡単には手を出せない。宣言されたプロパティを使えば、賢い人たちはアクセッサを介してかなり簡単にアクセスし、変異させることができます。

パフォーマンス

はい、場合によっては違いが出てくるかもしれません。プログラムによっては、プログラムの特定の部分でobjcメッセージングを使用できない制約があります(リアルタイムを考えてください)。また、速度のために直接アクセスしたいケースもあります。また、objcメッセージングが最適化のファイアウォールとして機能する場合もあります。最後に、参照カウントの操作を減らし、ピーク時のメモリ使用量を最小にすることができます(正しく行われた場合)。

非自明な型

例 C++の型がある場合、直接アクセスの方が良い場合があります。その型はコピーできないかもしれないし、コピーするのが面倒かもしれない。

マルチスレッド

あなたのアイバーの多くは共依存です。マルチスレッドのコンテキストでデータの整合性を確保する必要があります。そのため、クリティカルセクションの複数のメンバへの直接アクセスを推奨します。共依存データのアクセッサにこだわると、ロックは通常リエントラントでなければならず、多くの場合、より多くの取得を行うことになります(時には著しく多く)。

プログラムの正しさ

サブクラスはどんなメソッドでもオーバーライドできるので、インターフェイスに書き込むのと、状態を適切に管理するのとでは、意味的に違いがあることがわかるかもしれません。プログラムの正しさのための直接アクセスは、特に部分的に構築された状態(初期化子や dealloc 直接アクセスを使用するのがベストです。また、アクセッサ、コンビニエンス・コンストラクタの実装でもよく見かけることがあります。 copy , mutableCopy およびアーカイブ/シリアライズの実装があります。

また、「Security」(セキュリティ)の観点からすると、「Security」(セキュリティ)は すべてのものがパブリックな読み書きアクセサを持つ の考え方から、実装の詳細やデータをうまく隠蔽する考え方へ。時には、正しいことをするために、サブクラスのオーバーライドがもたらす副作用を正しく回避することが必要です。

バイナリサイズ

デフォルトですべてをreadwriteと宣言すると、プログラムの実行を少し考えると、通常、必要のない多くのアクセッサメソッドを持つことになります。だから、プログラムに脂肪がつき、ロード時間も長くなる。

複雑さを最小化する

場合によっては、あるメソッドで書かれて別のメソッドで読まれるプライベートなboolのような単純な変数に対して、すべての余分な足場を追加、タイプ、維持することが完全に不要になることがあります。


プロパティやアクセサを使うことが悪いというわけではなく、それぞれに重要な利点と制約があります。多くのOO言語と設計へのアプローチのように、ObjCで適切な可視性を持つアクセッサを支持するべきです。しかし、そこから逸脱する必要がある場合もあります。そのため、私はしばしば、直接アクセスをivarを宣言した実装に制限することが最善だと思います(例えば、それを宣言します)。 @private ).


re Edit 1:

私たちの多くは、hiddenアクセサを動的に呼び出す方法を覚えています(名前さえ知っていれば...)。一方、私たちの多くは ではなく KVCを超える)目に見えないivarに適切にアクセスする方法を記憶しています。クラスの継続 役立つ しかし、それは脆弱性をもたらす。

この回避策は明白です。

if ([obj respondsToSelector:(@selector(setName:)])
  [(id)obj setName:@"Al Paca"];

今度はivarのみで、KVCなしで試してみてください。