web-dev-qa-db-ja.com

Objective-cメソッドはいつ定義しますか?

私はObjective-Cを学んでおり、C/C++のバックグラウンドを持っています。

  • オブジェクト指向C++では、親クラスで宣言されている場合でも、メソッドを定義(実装)する前に常にメソッドを宣言する必要があります。

  • 手続き型C、IIRCでは、後でファイル内にある同じコンパイル単位(つまり同じファイル)内の他の何かからのみ呼び出される限り、関数を定義するだけで済みます(他の場所で「extern」で宣言しないでください)。

  • さて、Objective-Cでは、外部の何かによって使用される場合にのみヘッダーファイルでセレクターを宣言する必要があり、.mファイルでセレクターを適切に構成して内部で呼び出すことができるようです。 .mファイル。また、デリゲートメソッドまたは継承されたメソッドが(再)定義されることはないようです。

私は正しい方向に進んでいますか? Objective-Cでセレクターを定義する必要があるのはいつですか?

34

Objective-Cメソッドの場合、一般的な方法は、公開するメソッドをヘッダーファイルの@interfaceセクションに配置して、他のコードに.hのみをインクルードし、コードの操作方法を理解できるようにすることです。順序ベースの「遅延宣言」は、Cの関数と同じように機能します。依存関係を解決できない場合を除いて、メソッドのプロトタイプをhave to宣言する必要はありません。順序付けですが、必要に応じて@implementation内にメソッドプロトタイプを追加できます。

そうです、あなたは正しい方向に進んでいます。継承されたメソッドのメソッドプロトタイプを繰り返さないでください。コンパイラはそれを親のヘッダーファイルで見つけます。デリゲートメソッドは、カテゴリ内のプロトタイプとして定義され(クラスにタックされ)、必要に応じて実装されますが、デリゲートはすでに定義されているため、メソッドプロトタイプを提供する必要はありません。 (明確にするためなどに必要な場合は、引き続き可能です。)

Objective-Cを学習しているだけなので、この回答の残りの部分は、要求したよりもはるかに詳細です。あなたは警告されました。 ;-)


変数を静的に入力すると(たとえば、idの代わりにMyClass*)、クラスが実装することをアドバタイズしないメソッドを呼び出そうとすると、コンパイラーは、実装するかどうかに関係なく警告します。 。変数を動的に入力した場合、コンパイラーは必要なものの呼び出しを停止せず、存在しないものを呼び出した場合にのみランタイムエラーが発生します。言語に関する限り、実行時にエラーなしでクラスが実装する任意のメソッドを呼び出すことができます。メソッドを呼び出すことができるユーザーを制限する方法はありません。

個人的には、これは実は良いことだと思います。私たちはコードをカプセル化して他のコードから保護することに慣れているため、発信者を信頼できる同僚や顧客ではなく、悪意のある悪党として扱うことがあります。誰もが境界を尊重し、自分のことを自分でやるという「あなたはあなたの仕事をし、私は私の仕事をする」という考え方でコーディングするのはとても楽しいと思います。 Objective-Cの「態度」は、厳格な施行ではなく、コミュニティの信頼の1つであると言えます。たとえば、私の机に来る人を喜んで助けますが、誰かが私のものを台無しにしたり、質問せずに物を動かしたりすると、本当にイライラします。適切に設計されたコードは、妄想的または反社会的である必要はなく、単に連携して機能する必要があります。 :-)

とはいえ、インターフェイスをユーザーに公開する際に必要な粒度のレベルに応じて、インターフェイスを構造化するための多くのアプローチがあります。パブリックヘッダーで宣言するメソッドは、基本的に誰でも使用できる公正なゲームです。メソッド宣言を非表示にすることは、車や家をロックすることに少し似ています。おそらく、全員を締め出すことはできませんが、(1)いじってはいけないことで誘惑しないことで、「正直な人を正直に保つ」ことができます。(2 )参加する人は誰でも、彼らが想定されていなかったことを確かに知っており、否定的な結果について本当に文句を言うことはできません。

以下は、ファイルの命名に使用するいくつかの規則と、各ファイルに含まれる内容です。下部の.mファイルから始まり、各ファイルにはその上のファイルが含まれています。 (インクルードの厳密なチェーンを使用すると、シンボルの重複警告などを防ぐことができます。)これらのレベルの一部は、Cocoaフレームワークなどのより大きな再利用可能なコンポーネントにのみ適用されます。必要に応じてそれらを適応させ、あなたに合った名前を使用してください。

  • MyClass.h —パブリックAPI(アプリケーションプログラミングインターフェイス)
  • MyClass_Private.h —社内SPI(システムプログラミングインターフェイス)
  • MyClass_Internal.h —プロジェクト内部IPI(内部プログラミングインターフェイス)
  • MyClass.m —一般的にすべてのAPI/SPI/IPI宣言の実装
  • MyClass_Foo.m —カテゴリなどの追加の実装

APIは誰でも使用でき、一般にサポートされています(通常はFoo.framework/Headersで)。 SPIは、コードの内部クライアントに追加機能を公開しますが、サポートが制限される可能性があり、インターフェイスが変更される可能性があることを理解しています(通常はFoo.framework/PrivateHeaders)。IPIは実装で構成されます-プロジェクト自体の外部で使用してはならない特定の詳細。これらのヘッダーはフレームワークにまったく含まれていません。SPIおよびIPI呼び出しを使用することを選択した場合は、自己責任で行ってください。そして通常、変更がコードを壊すと彼らに不利益をもたらします。:-)

78
Quinn Taylor

ヘッダーファイルでメソッドを宣言すると、コンパイラの警告のみが停止します。 Objective-Cは動的言語であるため、そのメソッドが外部で宣言されているかどうかに関係なく、オブジェクトに対してメソッドを呼び出す(メッセージを送信する)ことができます。

また、.mファイルでメソッドを呼び出すコード(遅延宣言)の上にメソッドを定義した場合、警告は生成されません。同じことが当てはまりますが、宣言せずにオブジェクトにメッセージを送信できます。

もちろん、これは、Objective-Cにプライベートメソッドがないことを意味します。クラスが実装する任意のメソッドを呼び出すことができます。

個人の好み。パブリックメソッド(つまり、外部で使用されるメソッド)の場合。 .hで宣言し、.mで定義します。可視性を制限する場合、または少なくともプライベートメソッドであることを示す場合は、.mファイルで categories/class extension を使用します。多くのサンプルコードは遅延宣言メソッドを使用していますが。

6
Abizern

Objective-Cは関数を「メッセージ」として扱うため、「メッセージ」を任意のオブジェクトに送信できます。オブジェクトが受け入れることができることをインターフェイスに明示的に記述していない場合でも同様です。その結果、Obj-Cにはプライベートメンバーのようなものはありません。

これは非常に強力な場合がありますが、新しいObj-Cプログラマー(特にC++、JavaまたはC#)のプログラマーにとっては混乱の原因になります。基本的なルールは次のとおりです。

  • @interfaceですべてのパブリックメソッドを定義して、処理する予定のメッセージをコンシューマーが認識できるようにする必要があります。
  • コンパイラメッセージを回避し、@ implementationでメソッドを順序付ける必要がないように@interfaceで@privateメソッドを定義する必要があります。
  • クラスのメソッドの特定の規則を実装するときは、プロトコルを使用する必要があります。

これの多くは個人的な好みですが、迷惑なコンパイラ警告を回避し、コードを整理するのに役立ちます。わかりやすいです。

3
LBushkin