[objective-c] @class対#import



7 Answers

3つの簡単なルール:

  • ヘッダーファイル( .hファイル)にスーパークラスを#import 、プロトコルを採用しました。
  • #import all classes、およびprotocolsでは、実装( .mファイル)にメッセージを送信します。
  • 他のすべての宣言を転送します。

実装ファイルで前方宣言を行うと、おそらく間違ったことが起こります。

Question

ClassAがClassBヘッダを含む必要がある場合には、前方クラス宣言を使用する必要があり、ClassBヘッダには循環的な包含を避けるためにClassAヘッダを含める必要があることは、私の理解である。 私はifndefは単純なifndefなので、インクルードは一度しか起こらないことも理解しています。

私の質問はこれです: #importいつ使うの@classか? @class使うのは@classですか? @class宣言を使用すると、次のような一般的なコンパイラの警告が表示されることがあります。

warning: receiver 'FooController' is a forward class and corresponding @interface may not exist.

@class forward-declarationを削除し、 @classを投げてコンパイラが私に与えている警告を黙らせるのと@class 、これを理解するのが大好きです。




別の利点:クイックコンパイル

ヘッダーファイルをインクルードすると、そのファイル内の変更によって現在のファイルもコンパイルされますが、クラス名が@class nameとして含まれている場合はそうではありません。 もちろん、ソースファイルにヘッダーを含める必要があります




変数を宣言しようとすると、ヘッダファイルにまだインポートしていないプロパティを宣言しようとすると、コンパイラがこのクラスを知らないというエラーが表示されます。

あなたの最初の考えはおそらく#importそれです。
これにより、場合によっては問題が発生することがあります。

たとえば、ヘッダーファイルや構造体などに複数のCメソッドを実装する場合は、複数回インポートする必要がないためです。

したがって、 @classコンパイラに伝えることができます:

あなたがそのクラスを知らないのは分かっていますが、それは存在します。 それは他の場所で輸入されたり実行されたりするだろう

基本的には、このクラスが実装されるかどうか不明な場合でも、コンパイラにシャットダウンしてコンパイルするように指示します。

通常は、 .hファイルの.mおよび@class#importを使用します。




必要に応じてヘッダーファイルで前方宣言を使用し、実装で使用しているクラスのヘッダーファイルを#importします。 つまり、実装で使用しているファイルを常に#importします。ヘッダーファイルでクラスを参照する必要がある場合は、前方宣言も使用します。

ただし 、ヘッダーファイルで継承しているクラスまたは正式なプロトコルを#importする必要があります(この場合、実装でインポートする必要はありません)。




コンパイラは、コンパイラがその実装を知る必要があるような方法でそのクラスを使用する場合にのみ、不平を言うでしょう。

例:

  1. これはあなたがそのクラスを派生させようとしている場合、または
  2. あなたはそのクラスのオブジェクトをメンバ変数として持つことになります(まれですが)。

それをポインタとして使うつもりであれば、文句はありません。 もちろん、オブジェクトをインスタンス化するためにクラスの内容を知る必要があるので、実装ファイル内に#importする必要があります(そのクラスのオブジェクトをインスタンス化する場合)。

注:#importは#includeと同じではありません。 つまり、循環インポートと呼ばれるものはありません。 importは、ある情報のためにコンパイラが特定のファイルを探す要求のようなものです。 その情報がすでに利用可能な場合、コンパイラはそれを無視します。

これを試してみてください.AhをBhとBhにインポートしてください。問題や苦情はなく、うまくいくでしょう。

@classを使用する場合

ヘッダーにヘッダーをインポートしたくない場合にのみ@classを使用します。 これは、あなたがそのクラスが何であるかを気にしない場合もあります。 そのクラスのヘッダーがまだない場合もあります。

たとえば、2つのライブラリを作成している可能性があります。 1つのクラスは、1つのライブラリに存在するAという名前です。 このライブラリには、2番目のライブラリのヘッダが含まれています。 そのヘッダーはAのポインターを持つかもしれませんが、再度それを使う必要はないかもしれません。 ライブラリ1がまだ利用できない場合、@ classを使用するとライブラリBはブロックされません。 しかし、Ahをインポートしようとすると、ライブラリ2の進捗状況がブロックされます。




ファイル依存関係の詳細については、#import&@classを参照してください。

http://qualitycoding.org/file-dependencies/ itis良い記事

記事の要約

ヘッダーファイルのインポート:

  • #継承しているスーパークラスをインポートし、実装しているプロトコルを#importします。
  • フォワード - 他のすべてを宣言します(ただし、マスターヘッダーを含むフレームワークからのものでない限り)。
  • 他のすべての#importを削除してみてください。
  • 依存関係を減らすために、独自のヘッダーでプロトコルを宣言します。
  • 前方宣言が多すぎますか? あなたは大クラスがあります。

実装ファイルのインポート:

  • 使用されていないクルフト#importsを除去する。
  • メソッドが別のオブジェクトに委譲して戻ったものを返す場合は、そのオブジェクトを#importするのではなく、そのオブジェクトを前方宣言してみてください。
  • モジュールを含めると、連続する依存関係のレベルの後にレベルを含める必要がある場合は、ライブラリになりたいクラスのセットを持つことができます。 マスターヘッダーを持つ別のライブラリとしてビルドしてください。そのため、すべてを単一の事前構築されたチャンクとして持ち込むことができます。
  • #importsが多すぎますか? あなたは大クラスがあります。



私はたくさんの "それはこの方法"を参照してくださいが、私は "なぜ?"への答えは表示されません

だから、あなたのヘッダに@classを入れ、実装で#importだけするのはなぜですか? 常に@class #importする必要があり 、作業を倍増しています。 あなたが継承を利用しない限り。 この場合、1つの@classに対して#importingを複数回実行します。 突然宣言にアクセスする必要がないと突然決定した場合は、複数の異なるファイルから削除することを忘れないでください。

同じファイルを複数回インポートすることは、#importの性質上、問題ではありません。 パフォーマンスのコンパイルも実際問題ではありません。 そうであれば、私たちが持っているすべてのヘッダファイルに#includeされたCocoa / Cocoa.hなどはありません。




これは、@classが必要なシナリオ例です。

同じクラスのデータ型を持つパラメータを持つヘッダファイル内にプロトコルを作成する場合は、@ classを使用できます。 別々にプロトコルを宣言することもできますが、これは単なる例に過ぎません。

// DroneSearchField.h

#import <UIKit/UIKit.h>
@class DroneSearchField;
@protocol DroneSearchFieldDelegate<UITextFieldDelegate>
@optional
- (void)DroneTextFieldButtonClicked:(DroneSearchField *)textField;
@end
@interface DroneSearchField : UITextField
@end



Related