2009-08-26 17 views
5

この少しの構文はObjective-Cで少し混乱しています。Objective-C:self.myObjectを呼び出す場合とmyObjectを呼び出す場合の両方

my.myObjectを呼び出すのはいつmyObjectを呼び出すのですか?

これは冗長なようですが、互換性はありません。

誰か教えてください。

+0

私は同様の記事を見つけました:http://stackoverflow.com/questions/1051543/should-i-use-self-keyword-properties-in-the-implementation – Jonah

答えて

8

あなたがそれらにアクセスしている場合、self.memberを使用する理由はあまりありません。代入を行う場合は、単純な@property (assign)パラメータ(例えば、保持、コピーなど)以上のことをしているなら、あなたが書いているコードを保存することができます。例:

myObject = anotherObject; 
self.myObject = anotherObject; 

2番目の選択肢は、あなたが実際に(保持カウントなどを増やし、コピーを取得)オブジェクトにあなたが望むように代入していることを保証します。 [self setMyObject:anotherObject]と変わりはありません。

普通の配列作業ではx[5]がどのように*(x + 5*sizeof(x))になるかと同様に、ドット表記がメッセージの代わりになるため、通常のメッセージよりもドット表記を使用する際のオーバーヘッドや効率性はありません。

1

同じクラスの実装内からプロパティアクセサーを呼び出すことはほとんどありません。クラスのインスタンスメソッドは、内部状態への便利なアクセスを持っているので、通常、その状態に直接アクセスするのが理にかなっています。

合成されたアクセサを使用している場合は、それらを呼び出すだけで不必要なオーバーヘッドが追加されます。アクセサーがより複雑な実装を持つ場合、コードの目的が不明瞭になります。

最後に、Objective-Cを初めて使用している人は、self.propertyの構文と合成されたアクセサを使用して、Cocoaのメモリ管理を理解する必要がなくなります。あなたは本当にそれがどのように動作するかを知る必要があります。そうすることを避けようとすると、生産性が低下します。

+0

あなたがオブジェクトの内部状態すべてのウィリーニリーはあなたがすべきことを意味しません。そして、あなたがメモリ管理の仕組みがどのようにして完璧にそれを行うことになるわけではないことを理解したからです。たくさんのメソッドの中でメモリ管理責任を重複させることは、バグを求めています。 – Chuck

+0

私は正直に同意しない。あなたのクラスに@ synthesize'dアクセサがたくさんある場合、それらはおそらくあまり設計されていません。重要ではないアクセサを実装した場合は、それらを適切に使用するように注意する必要があります。 プロパティアクセサは、クラスの*外部*インターフェイスを作成するために使用するためのものです。クラスによって内部的に外部インターフェイスを使用することは時として意味がありますが、それは不必要(または非生産的)であることがよくあります。 –

+0

いずれにしても、実際にアクセサを使用する場合は、「自己」を使用します。文法は何が起こっているかを隠しているので、とにかく明示的なメッセージングを使うべきです。プロパティを設定している場合、 "[self setFoo:value]"は "self.foo = value"よりも5文字だけ長くなります。読み取りアクセスの場合、その差はさらに小さくなります。 コードを一度書くだけなので、後で読んだときに何が起きているのかを明確にするようにしてください。 –

1

コアデータを使用している場合は、永続ストアから必要になるまでいくつかのプロパティがロードされない可能性があるため、必ずアクセサーを使用してください。 (とにかく、あなたはSQLiteのストアを使用していると仮定。)

あなたがコアデータを使用していない場合、あなたは唯一の値を読み取るならちょうど直接myObjectを使用することが一般的に安全です。 myObjectの値を変更する場合は、そのプロパティの値を監視している他のオブジェクトが正しく通知されるようにアクセサを使用する必要があります。つまり、

// 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. 

一般に、オーバーヘッドはほとんどありません。私は同じオブジェクト内であっても、常にアクセサを使用することを好みます。 (もちろん、イニシャライザでの使用についての議論がありますが、これは別の問題です。)

3

Hrm、私はMarkまたはCinder6に同意するとは言えません。

私は最初の部分で同意します。 :self.foo-fooメソッドを呼び出しています。プレーンfoofoo ivarにアクセスしています。

ほとんどの場合、常にあなたのメソッドを実行する必要があります。彼らは、あなたを実際のストレージから引き離し、必要な他の動作から離れさせるためにそこにあります。後でクラスをサブクラス化するとどうなるか考えてみてください。ほとんどの場合、あなたがカバーする機能にアクセスする場所で独自のパブリックメソッドを呼び出すことになります。

例外はオブジェクトのinitとteardownであり、合成しないときはプロパティアクセサ自体の中にあります。オブジェクトのinitおよびteardown中にを実行すると、メソッドのサブクラス実装が呼び出されないようにします。これらのメソッドは、部分的に設定された状態でオブジェクトを処理する必要がないためです。

0

解凍した解答はありません。ただし、時期尚早の最適化は悪いことに注意してください。 MacのCocoaやiPhoneの場合、アクセサ/プロパティの使用はKVO準拠である必要があります。コアデータとCocoaバインディングが自動的に機能するには、KVOの適合性が必要です。コアデータでは、プロパティを変更するときだけでなく、アクセスするときにもKVOを確認する必要があります。

プロパティメモリの管理動作を確実にしたい場合は、アクセッサ/プロパティを使用することをお勧めします。つまり、setterまたはドット表記を使用するようにivarを設定する場合、およびフォローするメモリ管理パターン、ivarを取得するときに常にアクセサ/プロパティを使用するようにします。

さまざまなメモリ管理パターンがあります。すべての壊れていないオブジェクトは、アクセッサによって返されたオブジェクトが少なくとも現在のオートリリーススコープの終わりまで生き残ることを保証します。つまり、オブジェクトは明示的に保持され、現在の自動解放スコープで自動解放されます。アップルが推奨する方法はゲッターで明示的にこれを行います:

- (id)foo {return [[foo retain] autorelease]; } 
- (void)setFoo:(id)aFoo { 
    if(! [aFoo isEqual:foo]) { 
    [foo release]; 
    foo = [aFoo retain]; 
    } 
} 

それは、彼らが合成されたアクセサに従ったパターンだ暗示です。個人的に、私はセッターで自動解放することを好む:これは、新しい値でそれを交換する前に、古い値をautoreleasees

- (id)foo {return foo;} 
- (void)setFoo:(id)aFoo { 
    [foo autorelease]; 
    foo = [aFoo retain]; 
} 

。これは、ゲッターでの保持とオートレリースとまったく同じ効果を持ちますが、オブジェクトはオートレリープールに一度だけ追加する必要があります。ほとんどの場合、1の保持カウントを持ち、オートレリースされていないので、何が起きてもどこにも行きません。プロパティが、まだそれを保持しているコード(代理コールバックにあります)の間に置き換えられた場合、それはそのプロパティの下から消えません。

アクセサー/プロパティを使用すると、コードの他の部分がなくても必要な限り、オブジェクトが周囲から離れないようにすることができます。

アクセサー/プロパティを常に使用する最後の最良の理由は、プロパティごとに1つ少ない仮説を作成するということです。つまり、そのプロパティの基礎となるivarがあり、同じ名前(これは2つの仮定があります) 。おそらく将来、ivarを派生したアクセサに置き換えたいと思うでしょう。プロパティ表記法は引き続き機能します。おそらくあなたはアイバールの名前を変更したいと思うでしょう。プロパティはまだ動作します。幸いにも、Xcodeのリファクタリングは、通常、依存することができますが、なぜ悩ますのでしょうか?

オブジェクト指向プログラミングのポイントは、クラスで定義されたインターフェイスを使用することです。クラスが独自のインターフェースを無視するには、(多くの偏見的で合理的なものがあるにもかかわらず)正当な理由はありません。アクセサー自体を除くすべてのメソッドは、一般的にオブジェクトを無神論とし、内部状態をプライベートとして扱うべきです。すべてのメソッドをカテゴリまたはサブクラスのように記述し、ivarsをプライベートな状態として扱います。具体的なデザインでは、そうでなければ直接指示する必要はありません。イーバールに直接アクセスするのには、十分な理由がたくさんありますが、ケースバイケースで決まります。

+0

getter/setterメソッドは、Appleのメソッドと同じではありません。あなたのゲッターは、基本的にあなたが "代入"プロパティーに使うもので、セッターが "保持"プロパティーのものです。私はそれがほとんどの時間で動作すると確信していますが、私はあなた自身のオートリリースプールを使用し始めると元気になると思います。残りのココアで使用されている規則に従うことをお勧めします。 –

関連する問題