2

Objective-Cでは、このクラスのユーザーに公開されているgetterとsetterを使用したインスタンス変数のように、プロパティを追加@propertyおよび作成できます。@synthesize

この場合、インスタンス変数を宣言して公開するのと同じではありませんか?そうすれば、ゲッターとセッターをメソッドとして呼び出すオーバーヘッドはなくなります。数値を0から100の間に制限するなど、セッターの検証を行う可能性がありますが、それ以外の場合、パブリックインスタンス変数は同じことをより速く達成しませんか?

4

6 に答える 6

3

によって生成されたアクセサのみを使用している場合でも、@synthesizeいくつかの利点があります。

  1. メモリ管理:生成されたセッターは、(retain)プロパティの新しい値を保持します。クラスの外部からオブジェクトivarに直接アクセスしようとすると、クラスがそれを保持できるかどうかわかりません。(これはARCではそれほど問題にはなりませんが、それでも重要です。)

  2. スレッドセーフアクセス:生成されたアクセサーはデフォルトでアトミックであるため、複数のスレッドからプロパティにアクセスする競合状態について心配する必要はありません。

  3. キーバリューコーディングと観察: KVCは、さまざまなシナリオでプロパティへの便利なアクセスを提供します。述語を設定するときにKVCを使用するか(たとえば、オブジェクトのコレクションをフィルタリングするために)、コレクション内のプロパティを取得するためにキーパスを使用することができます(たとえば、クラスのオブジェクトを含むディクショナリ)。KVOを使用すると、プログラムの他の部分がプロパティの値の変更に自動的に応答します。これは、MacのCocoa Bindingsでよく使用され、プロパティの値にバインドされたコントロールを持つことができます。また、CoreDataでも使用されます。両方のプラットフォーム。

これらすべてに加えて、プロパティはカプセル化を提供します。クラスのインスタンスを使用する他のオブジェクト(クライアント)は、生成されたアクセサーを使用しているかどうかを知る必要はありません。クライアントコードを変更することなく、他の便利なことを行う独自のアクセサーを作成できます。ある時点で、クラスがそのivarの1つに外部から加えられた変更に対応する必要があると判断する場合があります。すでにアクセサーを使用している場合は、クライアントにアクセサーの使用を開始させるのではなく、アクセサーを変更するだけで済みます。または、Appleは、生成されたアクセサを将来のOSバージョンでより良いパフォーマンスまたは新機能で改善することができ、クラスの残りのコードもそのクライアントも変更する必要はありません。

于 2012-04-14T22:19:26.437 に答える
3

オーバーヘッドは実際の問題ではありません

最後の質問に答えると、はい、オーバーヘッドが発生しますが、特に最新のプロセッサの能力を考慮すると、もう1つのフレームをプッシュしてスタックからポップするオーバーヘッドはごくわずかです。パフォーマンスに関心がある場合は、アプリケーションのプロファイルを作成し、実際の問題がどこにあるかを判断する必要があります。いくつかのアクセサーを削除するよりも、最適化するのに適した場所が見つかることを保証します。

いいデザインだ

プライベートメンバーをカプセル化し、アクセサーとミューテーターで保護することは、優れたソフトウェア設計の基本原則にすぎません。ソフトウェアの保守、デバッグ、および拡張が容易になります。他の言語についても同じ質問をするかもしれません。たとえば、Javaクラスですべてのフィールドを公開しないのはなぜですか。(Rubyのような言語を除いて、インスタンス変数を公開することは不可能だと思います)。肝心なのは、ソフトウェアがどんどん大きくなるにつれて、真の地獄から身を守ることができるため、特定のソフトウェア設計手法が実施されているということです。

遅延読み込み

セッターでの検証は1つの可能性ですが、それ以上にできることがあります。ゲッターをオーバーライドして、遅延読み込みを実装できます。たとえば、ファイルまたはデータベースからいくつかのフィールドをロードする必要があるクラスがあるとします。従来、これは初期化時に行われます。ただし、オブジェクトをインスタンス化する人がすべてのフィールドを実際に使用するわけではない可能性があるため、代わりに、ゲッターを介して要求されるまで、それらのメンバーを初期化するのを待ちます。これにより、初期化がクリーンアップされ、処理時間をより効率的に使用できるようになります。

ARCでのサイクルの保持を回避するのに役立ちます

最後に、プロパティを使用すると、ARCでブロックを使用したループの保持を簡単に回避できます。ivarsの問題は、それらにアクセスするときに、暗黙的に自分自身を参照していることです。だから、あなたが言うとき:

_foo = 7;

あなたが本当に言っているのは

self->_foo = 7;

したがって、次のようになります。

[self doSomethingWithABlock:^{
    _foo = 7;
}];

これで、保持サイクルができました。必要なのは弱いポインタです。

__block __weak id weakSelf = self;
[self doSomethingWithABlock:^{
    weakSelf->_foo = 7;
}];

さて、これは明らかにセッターとゲッターの問題ですが、明示的にself.propertyを呼び出す必要があるため、weakSelfの使用を忘れる可能性は低くなりますが、ivarは暗黙的にselfによって参照されます。プロパティを使用している場合、静的アナライザーはこの問題を解決するのに役立ちます。

于 2012-04-14T23:40:43.193 に答える
1

@property公表された事実です。他のクラスに、クラスのプロパティを取得でき、場合によっては設定できることを通知します。プロパティは変数ではなく、文字通りその言葉が言うことです。たとえばcount、はのプロパティですNSArray。それは必ずしもインスタンス変数ですか?いいえ。それがそうであるかどうかを気にする必要がある理由はありません。

@synthesize自分で定義していない限り、デフォルトのゲッター、セッター、インスタンス変数を作成します。これは実装固有です。それはあなたのクラスが財産を提供するという契約上の義務を果たすために選択する方法です。これはプロパティを提供する1つの方法にすぎず、他の人に通知することなく、いつでも実装を変更できます。

では、ゲッターとセッターを提供する代わりに、インスタンス変数を公開してみませんか?それはクラスの実装にあなたの手を縛るからです。他の行為は、公開するために選択したインターフェースだけでなく、コーディングされた特定の方法に依存するようになります。これにより、壊れやすく相互依存するコードがすぐに作成され、壊れてしまいます。それはオブジェクト指向プログラミングへの嫌悪感です。

于 2012-04-14T20:26:28.373 に答える
1

通常、データと実装のカプセル化と非表示に関心があるためです。保守が簡単です。すべてではなく、1つの実装を変更する必要があります。実装の詳細はクライアントから隠されています。また、クライアントは、クラスが派生クラスであるかどうかを考える必要はありません。

于 2012-04-14T21:17:15.773 に答える
1

あなたは正しいです...いくつかの非常に限られたケースのために。プロパティは、ピクセル、画像、およびリアルタイムオーディオDSP(など)コードの内部ループで使用される場合、CPUサイクルパフォーマンスの点でひどいものです。使用頻度が少ない場合は、読み取り可能で保守可能な再利用可能なコードに関して多くの利点があります。

于 2012-04-15T05:15:32.613 に答える
0

@propertyと@synthesizeが設定され、getterメソッドとsetterメソッドを取得しています

他の使用法は、他のクラスでもその変数を使用できることです

変数をインスタンス変数として使用し、カスタムのゲッターメソッドとセッターメソッドを使用する場合は実行できますが、変数の値を設定し、変数の値を取得しているときにゾンビになり、アプリがクラッシュする場合があります。

したがって、プロパティは、クラスのオブジェクトの割り当てを解除するまでオブジェクトを解放しないようにオペレーティングシステムに指示します。これが役立つことを願っています。

于 2012-04-14T21:07:56.853 に答える