35

かなり新しい Objective-C プログラマー (4 年間の Java 経験) として、クラス拡張をいつ使用するかを理解するのに苦労しているようです。私が理解したことから (間違っている場合は訂正してください)、カテゴリと拡張機能の主な違いは、拡張機能ではメインの実装内でメソッドを実装することを期待しているのに対し、カテゴリでは別の実装にすることができることです。 . また、主にプライベート メソッド用に拡張機能を使用しているようです。

これが私の最初の質問です。クラス拡張を使用してプライベート メソッドを宣言する場合と、まったく宣言しない場合の違いは何ですか (どちらの場合も実行時にコンパイルされるようです)。(例 1 対 2)

例 1

@interface Class()
-(void) bar;
@end

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

例 2

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

2 番目の質問: 拡張機能内で ivar を宣言することと、実装内で直接宣言することの違いは何ですか? (例 3 対 4)

例 3

@interface Class() {
    NSArray *mySortedArray;
}
@end

@implementation Class
@end

例 4

@implementation Class
NSArray *mySortedArray;
@end

コーディング規約について最後に質問があります。変数名の前にアンダースコア (_) を付ける必要があるのはいつですか?

ありがとうございました

4

5 に答える 5

28

クラス拡張のメソッド

プライベート メソッドを宣言する必要がないというケースは、かつてはありませんでした。最近まで、どこかでプライベート メソッドを宣言する必要があり、ほとんどの人はそのためにクラス拡張を選択していました。Xcode 4.4 (と私は信じています) から、コンパイラは、その実装内でどのメソッドがプライベートになることを意図しているかを判断するのに十分なほど賢く、他の場所でそれらを宣言する必要を取り除きます。

クラス拡張の変数

例 3 と 4 については、注意してください。クラス拡張内では、変数はそのクラスのインスタンス変数です (例 3)。例 4 では、グローバル変数を宣言しています (C のグローバル変数セマンティクスに従っているため)。プライベート インスタンス変数の例 3 に固執します。

コーディング規約

コーディング規約に関しては、アンダースコアを使用するかどうかを決定するのは開発者/チーム次第です。私たちのチームはm_、プライベート インスタンス変数に使用します。Apple のドキュメントでは、アンダースコアを使用することを提案しています (これは、合成されたプロパティの基になるインスタンス変数の命名スタイルです)。重要なことは、コード全体で一貫性を保つことです。

于 2013-02-03T17:52:13.170 に答える
8

カテゴリと拡張機能の主な違いは、拡張機能ではメインの実装内でメソッドを実装することを想定しているのに対し、カテゴリでは別の実装に実装できることです。また、主にプライベート メソッド用に拡張機能を使用しているようです。

正しい。

クラス拡張を使用してプライベート メソッドを宣言する場合と、まったく宣言しない場合の違いは何ですか (どちらの場合も実行時にコンパイルされるようです)。

宣言されていないセレクターに関するコンパイラーの警告かもしれません。(もちろん問題なく動作します - メソッドは実装されており、存在します。) また、コンパイラが ABI 準拠の正しいバイナリ コードを出力するには、宣言 (既知の正しい関数シグネチャ) が必要であることに注意してください。宣言されていないメソッド (つまり、id可変引数を返し、受け入れる) についての仮定は正しくない可能性があります。互換性のない型のポインターを介して関数を呼び出すことは、未定義の動作です。

拡張機能内で ivar を宣言することと、実装内で直接宣言することの違いは何ですか?

4 番目の例では、これはグローバル C 変数であり、クラスのインスタンス変数ではありません。

変数名の前にアンダースコア (_) を付ける必要があるのはいつですか?

必要なときはいつでも、一貫して実行してください。常にまたは決して。

于 2013-02-03T17:46:14.163 に答える
2

質問 1 の例 2: Class に実装されているメソッド foo と bar は、Class のインスタンスから見えます。foo と bar が別のヘッダー ファイルで宣言されておらず、実装ファイルが使用可能にされていない場合、別のクラスは foo と bar の存在を認識しません。foo と bar はプライベート メソッドです。Class のインスタンスは引き続き foo および bar メッセージに応答します。また、Xcode は foo と bar が存在することを (ヘッダー ファイルで宣言せずに) 検証できないため、foo と bar にメッセージを送信しようとする別のクラスが存在する場合、Xcode は警告を発します。対照的に、例 1 の bar の宣言により、他のクラスはメッセージ bar を Class のインスタンスに送信できます。@interface Class が他のクラスによって #import されているヘッダー ファイルにある場合、Xcode は bar へのメッセージのエラー フラグも立てません。

質問 2 の例 4: mySortedArray は、クラス内のローカル スコープで宣言されたローカルの不変配列です。例 3 の mySortedArray は、Class のインスタンスを作成する他のクラスからアクセスできる NSArray 型のインスタンス変数です。

于 2013-02-03T17:48:41.163 に答える