4

私は、自分自身を介してインスタンス変数にアクセスするか、名前だけでインスタンス変数にアクセスするか(クラス内で作業する場合)の違いについて混乱しています。

たとえば、次のクラスを取り上げます。

//In .h file:
@interface Register : NSObject {
    NSString *mName;
}

- (id) initWithName:(NSString *) name;

//In .m file:
- (id) initWithName:(NSString *)name
{
    if (self == [super init])
    {
        mName = name;
    }
    return self;
}

経由でインスタンス変数にアクセスすることの違いは何ですか

self.mName = name;

mName = name;

これは @property ではなく、@sythenize されていません。

ただし、この例では次のようになります。

//In .h file:
@interface Manange_My_ViewsViewController : UIViewController { 
    IBOutlet UILabel *countLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *countLabel;

//In .m file:
@synthesize countLabel;

- (void) updateLabel:(NSUInteger)count
{
    countLabel.text = [NSString stringWithFormat:@"%d", count];
}

しかし、countLabel に次のようにアクセスしたとします。

self.countLabel

違いは何ですか?

編集: ユーザーの回答ごとの 3 番目の例: iVar が IBOutlet ではなかったとします:

//In .h file:
@interface Fake : NSObject {
    NSString *mVar;
}
@property (nonatomic, retain) NSString *mVar;

//In .m file:
 @synthesize mVar;

 mVar = @"";

VS

 self.mVar = @"";

それとも同じですか - 最初に実際のインスタンス変数にアクセスし、2 番目に (@synthesize を介して) 自動作成されたセッターを実際に通過しますか?

皆さんありがとう!

編集:Peter Hoseyに応じて更新...

では、mVarName の慣例は悪いと思いますか? 私はC++時代からそれを取りました。

しかし、あなたがそうする場合はどうですか?

-(void) someMethod:(int) x
{
    x = x;
}

それはできません(「x」もクラス変数であるとします)

しかし、次のことができます。

-(void) someMethod:(int) x
{
    mX = x;
}

しかし、あなたの言うことは、次のことを行う方が良いです:

-(void) someMethod:(int) x
{
    self.x = x;
}
4

3 に答える 3

7

経由でインスタンス変数にアクセスすることの違いは何ですか

self.mName = name;

vs

mName = name;

1つ目は、プロパティアクセス構文です。これは、オブジェクト(この場合はself)へのアクセサーメッセージに変換されます。つまり、そのステートメントは暗黙的に次のメッセージ式ステートメントに変換されます。

[self setMName:name];

(そのような厄介なアクセサ名は、「mName」がプロパティの不適切な名前である理由です。これを回避するためのプロパティ宣言構文があり、プロパティに「name」とインスタンス変数に「mName」という名前を付けて、一方を他方にマップできます。 。)

2番目の例では、インスタンス変数に直接アクセスします。アクセサーメッセージはありません。

これは@propertyではなく、@sythenizeされていません。

でもこれだと言って…</p>

「<code>mName」という名前のプロパティがクラスに対して宣言されていない場合、プロパティアクセス構文を使用して、そのクラスのインスタンスでその名前のプロパティにアクセスすることはできません。

@dynamicまた、アクセサを合成するか、を使用してスーパークラスにハンドウェーブするか、自分で定義するかは関係ありません。これがオブジェクトがアクセサメッセージに応答する方法ですが、コンパイラが生成するアクセサメッセージも同じです(プロパティアクセスはクラスの内部からと同じようにクラスの外部からも簡単に取得できるため)。

iVarがIBOutletではなかったとしましょう。

それは問題ではありません。IBOutletは、IBにとって何でも意味します。他のすべては気にしません。

実際、IBOutletは現在、何にも拡張されない単なるマクロです。コードが前処理されると、「IBOutlet」という単語は存在しなくなるため、コンパイラーはそれを認識しません。それは、それがIB以外のものに与える違いがどれほど小さいかです:まったくありません。

質問編集に応じて編集する

それに続くアクセサ名のために、プロパティ名mNameとしては悪いと言いました。インスタンス変数の名前は別の問題です。特に、プロパティとivarが同じ名前である必要はないためです。

変数の場合、それがインスタンス変数であろうとローカル変数であろうと、またはの選択はname純粋にスタイルの選択です。m_namemName

someMethod:通常はアクセサですsetX:。そのメソッド内で、つまりself.x = x[self setX:x]は無限再帰を引き起こします。だからそうしないでください。

someMethod:がアクセサ(またはinitまたは)でない場合はdealloc、プロパティを使用するだけで問題なく、一般的に推奨されます。ただし、その場合、引数の1つにインスタンス変数と同じ名前を付けることはほとんどありません。このような場合は、ローカル変数の目的がより具体的であるため、より具体的に名前を付けてください。これもスタイルの問題です。

それがアクセサーでnewXある場合、インスタンス変数にプロパティと同じ名前を付けて、ローカル変数に名前を付けますx。これは私自身の個人的なスタイルです。私が言ったように、プロパティx、ivar mX、およびローカル変数に名前を付けることxも問題ありません(この例の過度の簡潔さは別として)。

于 2010-02-17T08:40:13.677 に答える
1

まず第一に、読み取り専用プロパティ (本質的には IBOutlet である) の場合、それほど重要ではありません。

主な違いは、インスタンス変数が直接アクセスされている間に、プロパティが実際にアクセサー メソッドを呼び出していることです。

したがって、retain プロパティを設定するには、self とアクセサーを使用して古いオブジェクトを解放し、新しいオブジェクトを保持します。インスタンス変数を直接設定しても、オブジェクトの保持数には影響しません。

を使用@synthesizeすると、標準のアクセサーが生成されます。

プロパティを使用する主な理由は、プロパティがアクセサであるため、クラスの外部から読み取りおよび/または変更できることです。

于 2010-02-17T05:01:49.113 に答える