私は最初のObjective-Cの本を読み始めたばかりで、ほとんど明確ですが、最初にインターフェイスでメソッドを宣言するように教えている理由を理解したいので、インターフェイスからメソッドを削除して、実装でそれを実行しようとしましたセクションとすべてが機能しているように見えるので、私の質問はそれが重要ですか?もしそうなら、これは何を達成するのに役立ちますか?
3 に答える
それはCです。ヘッダーで関数/メソッドを宣言すると、他のコンパイルユニットが関数プロトタイプを見て、それらに基づいてコンパイルできます。ただし、Objective-C は動的ディスパッチを介して動作するため、ヘッダーでメソッドを宣言しなくても、実行時に存在します。メソッドを呼び出すと、実行時に解決されるため、ヘッダーにあるかどうかは関係ありません。
唯一の問題は、ヘッダーにメソッドを含めない場合、コンパイラは戻り値と引数の型について仮定を行う必要があることです。デフォルトはid
、アーキテクチャに応じて 4 または 8 バイトです。そのため、実際の戻り値の型が異なるサイズ (構造体など) の場合、問題が発生しますBOOL
。
Objective-C は、意思決定を可能な限り遅らせる非常に動的な言語 (およびランタイム) です。
実行時にオブジェクトが指定したセレクターに実際に応答するため、コードは正常に実行されます。
ただし、メソッドを宣言することで、Objective-C コンパイラが、実行時に予期しない状況に遭遇しないことをチェックするのに役立ちます。
たとえば、次のクラスを取り上げます。
@interface MDFoo : NSObject
- (void)blah;
@end
@implementation MDFoo
- (void)blah {
NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
- (void)boo {
NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
@end
別のコントローラ クラスで、 のインスタンスを作成し、MDFoo
いくつかのメッセージを送信したいとします。
MDFoo *foo = [[MDFoo alloc] init];
[foo blah];
[foo boo]; // compiler warning
[foo yell]; // compiler warning
プログラムをコンパイルすると、最後の 2 つのメソッドが見つからず、 のインスタンスがMDFoo
それらのセレクターに応答しない可能性があるという警告がコンパイラから表示されます。
その後、プログラムを実行すると、次のように記録されます。
foo[10540:303] [MDFoo blah]
foo[10540:303] [MDFoo boo]
foo[10540:303] -[MDFoo yell]: unrecognized selector sent to instance 0x1001082f0
foo[10540:303] *** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[MDFoo yell]:
unrecognized selector sent to instance 0x1001082f0'
したがって、実行時に警告はboo
何もないことが判明しましたが、警告yell
は正しく、アプリケーションが終了しました。
設計の観点からは、どのメッセージを呼び出すことができるかを他のオブジェクトに知らせる方法でもあります。( Objective-C プログラミング言語: クラスの定義 - インターフェースの役割を参照)。
インターフェイス(ヘッダー)でメソッドを宣言して、公開する(他のクラスから/からアクセスできるようにする)必要があります。クラスの内部でのみメソッドを使用している場合は、インターフェイスで宣言する必要はありません。