Objective-Cプログラミング言語公式文書 (II) - オブジェクト、クラス、メッセージ
<スパン
声明 この文書は、参照を描画するために同胞の開発を促進するために、手の翻訳の唯一の個人的な学習プロセスです。あなたは、翻訳が良いか、または所定の位置にないと感じた場合は、訂正することを歓迎し、速やかに修正を行います。
オブジェクト、クラス、メッセージング
オブジェクトの基本
<スパン オブジェクト指向プログラミングは、オブジェクトを中心に構築されています。オブジェクトはデータに関連しており、ある操作によってそのデータに影響を与えることができる。つまり Objective-Cでは、これらの操作をオブジェクトのメソッドと呼びます。メソッドによって影響を受けるデータは、そのインスタンス変数です。(他の文脈では、インスタンス変数やメンバ変数を指すこともある)。基本的に、オブジェクトはデータ構造(インスタンス変数)と一連の処理(メソッド)を自身のプログラミングユニットに束ねる。
イド
Objective-Cでは、オブジェクトの識別子はidという別のデータ型になります。この型は、すべてのオブジェクトに使用できる汎用型であり、特定のクラスを無視し、クラスのインスタンスにも、クラスオブジェクト自体にも使用することができます。
id anObject;
について Objective-Cのオブジェクト指向の構成では、メソッドの戻り値であるidが、デフォルトのデータ型としてintに取って代わります。(厳密なC言語では、関数の戻り値であるintがデフォルトのデータ型として残っています。)
キーワード nil は、値 0 の空のオブジェクト、id,nil を定義するために使用され、次のことが可能です。 objc/objc.hでは 他のタイプの Objective-Cの基本型定義です。
次の例の id は、データコンストラクタへのポインタとして定義されています。
typedef struct objc_object {
<未定義
Class isa;
} *id;
以下の型の各オブジェクトは、それがどのクラスのインスタンスであるかを示すisa変数を持っています。これは、Class型自体がポインタとして定義されているためです。
typedef struct objc_class *Class;
isa
は、よく"にされます。
isa
ポインターです。
動的なタイプ
id型は全く厳密ではありません。それ自身は、もちろんそれがオブジェクトであることを除いて、オブジェクトに関するいかなる情報ももたらしません。ある意味で、プログラムは通常、オブジェクトについて、それが含んでいるよりももっと具体的な情報を得る必要があるのです。id型識別子はこの具体的な情報をコンパイラに提供しないので、これらのオブジェクトは、実行時にこの情報を提供できなければならないのです。
インスタンス変数isaは、そのオブジェクトがどのような種類のオブジェクトなのか、そのクラスを指定します。同じ動作(メソッド)と同じデータ(インスタンス変数)を持つオブジェクトは、同じクラスに属します。
このようなオブジェクトは、実行時に動的に型付けされる。ランタイムシステムは、必要なときにいつでも、オブジェクトに尋ねるだけで、そのオブジェクトが属する正確なクラスを見つけることができます。(ランタイムに関する情報は、テスト用の Objective-Cランタイム・プログラミング・ガイド 記事 ). Objective-Cの動的型付けは、後ほど詳しく説明する動的バインディングの基礎として役立っている。
<スパン isa変数はまた、オブジェクトがイントロスペクション操作、つまり自分自身(または他のオブジェクト)に関する情報を見つけることを可能にします。コンパイラは、ランタイムシステムで使用するために、データ構造の中にクラスの定義に関する情報を記録します。ランタイムシステムを使用する場合、オブジェクトが特定のメソッドを実装しているかどうかを判断したり、その親クラスの名前を調べたりすることができます。
ここでは、新しいメソッドを "クラス" の章で、オブジェクトクラスについて詳しく説明します。
また、ソースコードにクラス名を静的に入力することで、コンパイラにオブジェクトクラスに関する情報を提供することも可能である。クラスは型固有のオブジェクトであり、クラス名は型名として使用されます。を参照することができます。 "クラスの種類" と "静的動作を有効にする."
メモリ管理
どのようなアプリケーションでも、オブジェクトが使用されていないときに適切に解放されることを確認することは非常に重要です。そうしないと、アプリケーションは実際に必要とする以上のメモリトラックを持つことになります。また、使用中のオブジェクトを解放しないようにすることも重要です。
Objective-Cは、これらの目標を達成するために3つの方法を提供しています。
-
自動参照カウント (ARC) は、コンパイラがすべてのオブジェクトのライフサイクルを推論する自動参照カウントです
-
手動による参照カウント (MRC), Manual Reference Counting, MRR, または Manual Hold, Release と呼ばれることもある。オブジェクトのライフサイクルを完全に制御し、決定する場合に使用します。
-
ガベージコレクション オブジェクトのライフサイクルを決定する責任をオートサイクラーに渡すガベージコレクション。
を参照することができます。 ガベージコレクション プログラミングガイド . (ただし、このドキュメントはiOS-IOSには適用されません。IOS開発センターに行けば、ドキュメントを入手できます。
オブジェクトメッセージ
このセクションでは、メッセージの例外をネストする方法など、メッセージを送信するための構文に焦点を当てます。また、オブジェクトのインスタンス変数の可視領域の側面に関する問題についても説明します。また、ポリモーフィズムとダイナミックバインドの概念についても説明します。
メッセージ送信のための構文
オブジェクトに何かをさせるには、あるメソッドを要求するようにメッセージを送る必要があります。このメッセージは Objective-Cでは、メッセージの例外は角括弧で囲まれています。 ;を使用します。
<テーブル[receiver message]
受信者はオブジェクトであり、メッセージはそのオブジェクトに何をすべきかを指示する。ソースコードでは、時間とは単にメソッドの名前とそれに渡す必要のある引数のことである。メッセージが送信されると、ランタイムシステムは受信者の命令体系から適切なメソッドを選択し、それを呼び出す。
例えば、次のようなメッセージは
myRectangle
オブジェクトを実行します。display
メソッドを呼び出すと、矩形がそれ自身を表示するようになります。<テーブル[myRectangle display];
メッセージの後には、セミコロン " が付きます。
;
C言語のステートメントと同じように。メッセージ中のメソッド名は実装メソッドを選択するために使用されるため、一般にセレクタ( セレクタ ).
メソッドはパラメータを取ることができます。パラメータが1つのメッセージでは、パラメータの後にコロン (
:
を指定し、その後にパラメータの値<テーブル[myRectangle setWidth:20.0];
複数のパラメータを持つメソッドの場合は、パラメータが1つの場合と同様に、パラメータをスペースで区切り、同じくパラメータ名:パラメータ値という形式で記述します。
<テーブル[myRectangle setOriginX: 30.0 y: 50.0]; // This is a good example of
// multiple parameters
セレクタの名前には、上の例で見たように、コロンも含めたすべての部分と、もちろん戻り値の型やパラメータの型など、必要なものが含まれています。
備考 Objective-Cのセレクタ名の単語部分は任意ではなく、その順番を変更することはできません。他のいくつかの言語では、"named parameters" と "keyword parameters" は実行時に変更でき、デフォルト値を持ち、異なる順序にすることができ、追加の名前付きパラメータを持つことができる。これらの機能は、Objective-Cでは利用できません。いずれにせよ、Objective-Cのメソッド宣言は、単にCの関数に2つの引数を追加したものです( Objective-Cランタイム・プログラミング・ガイド のドキュメントを参照してください。 メッセージング" をご覧ください)。その結果、Objective-Cのメソッド宣言は、次のPythonの例で説明するように、Pythonなどの名前付き引数やキーワード引数を使用する言語とは異なる構造になっています。
<テーブルこのPythonの例ではdef func(a, b, NeatMode=SuperNeat, Thing=DefaultThing):
pass
Thing
とNeatMode
を呼び出すと、無視されたり、異なる値を持つことがあります。日常的な運用では
Rectangle
クラスを実装するためのシンプルな代替手段です。setOrigin::
メソッドを、次の例のように第2パラメータ用のタグを付けずに呼び出すことができます。<テーブル[myRectangle setOrigin:30.0 :50.0]; // This is a bad example of multiple parameters
は構文的に合法ですが
setOrigin::
は、メソッド名とパラメータを交差させません。つまり、第2引数にはタグがないのですが、それではこのコードを見ている人が、これらの引数が何をするものなのか混乱してしまいます。また、滅多にないことですが、メソッドがミュータブルなパラメータを持つことも可能です。追加のパラメータはカンマで区切ります。次の例では
makeGroup:
メソッドは、必須パラメータ(group
) と3つのオプションの引数があります。<テーブル[receiver makeGroup:group, memberOne, memberTwo, memberThree];
標準的なCの関数と同様に、メソッドは戻り値を持つことができます。
<テーブルBOOL isFilled;
isFilled = [myRectangle isFilled];
変数とメソッドは同じ名前を持つことができることに気づきます。
メッセージ式は、他のメッセージの中に入れ子にすることができます。次の例は、ある長方形の色を別の長方形の色に設定するものです。
<テーブル[myRectangle setPrimaryColor:[otherRect primaryColor]];
また、Objective-Cでは、カンマ(
.
この演算子は、オブジェクトのアクセス可能なメソッドを呼び出すのに便利なものです。カンマ演算子は一般的に、宣言されたプロパティと連結された機能に対して使用され、例えば ( "宣言されたプロパティ" )、カンマ演算子の構文は、以下のように記述することができます。 ドットシンタックス.quot.quot;nilにメッセージを送る
Objective-Cでは、nilへのメッセージ送信は有効ですが、実行時にはあまり効果がありません。Cocoaでは、この機能を利用する方法がいくつかあります。例えば メッセージも有効です :
-
このメソッドがオブジェクトを返した場合、送信されたメッセージは
nil
メッセージは0
(nil
). 例えば<テーブルPerson *motherInLaw = [[aPerson spouse] mother];
もし
spouse
オブジェクトはnil
であればmother
に送信されます。nil
を返し、このメソッドはnil
. -
このメソッドが任意のポインタ型を返す場合、任意の整数型の2つのテーブルの大きさは、小さいか
sizeof(void*)
, afloat
,double
,long double
またはlong long
にメッセージが送信されます。nil
が返されます。0
. -
もし、このメソッドが
struct
と同じように Mac OS X ABI関数呼び出しガイド がレジスタから戻るように定義されている場合、そのメッセージはnil
意志 各struct
のメンバーです。 返品0.0
, その他struct
データ型はゼロパットされない -
メソッドが前述の値型のいずれかを返す場合、送信された値型は
nil
メッセージは未定義の値を返します。
次のコード片は、メッセージを
nil
.<テーブルid anObjectMaybeNil = nil;
// this is valid
if ([anObjectMaybeNil methodThatReturnsADouble] == 0.0)
{
<未定義// implementation continues...
}
レシーバのインスタンス変数
メソッドは、取得したオブジェクトのインスタンス変数に自動的にアクセスすることができます。メソッドにパラメータとして渡す必要はありません。たとえば、上記のように
primaryColor
メソッドは引数を取らないので、やはり
原色が見つかり、返される。各メソッドは、引数として宣言することなく、Receiver とそのインスタンス変数を受け取ります。otherRect
この規約により、Objective-Cのコードはシンプルになります。また、オブジェクト指向のプログラマが求めるオブジェクトやメッセージもサポートします。メッセージをレシーバーに渡すのは、自宅に手紙を郵送してもらうようなものです。メッセージは、外から受け手に引数を運びます。受け手から自分自身に渡す必要はありません。
メソッドが自動的にアクセスできるのは、受信機から取得したインスタンス変数のみです。他のオブジェクトに格納されている変数について他の情報を要求する場合は、その変数の内容を取得するために、要求先のオブジェクトにメッセージを送信する必要があります。上記のような
primaryColor
とisFilled
メソッドが使用されます。インスタンス変数の詳細については クラスの定義"
ポリモルフィック
上記のいくつかの例のように、Objective-Cのメッセージは標準的な関数呼び出しのような機能性を示します。しかし、メソッドはオブジェクトに属しているため、メッセージは従来の関数呼び出しのように動作する必要はありません。
通常、オブジェクトは、そのオブジェクト用に設計したメソッドを操作することができます。他のオブジェクトのために設計したメソッドは、たとえメソッド名が同じであっても、それらを混乱させることはできません。しかし、2つのオブジェクトは、同じメッセージに対して異なる反応をすることができます。例えば、それぞれのオブジェクトは、同じメッセージに対して
display
メッセージは、そのメッセージ独自の方法で自分自身を表示することができます。と呼ばれるこの機能は ポリモーフィズム は、オブジェクト指向プログラミングにおいて非常に重要な役割を担っています。同様に重要なのが動的バインディングで、そのコードを書くときにオブジェクトの型が何であるかを選択することなく、多くの異なるオブジェクトに適用できるコードを書くことができるのです。また、後で開発され、他のプログラマーが他のプロジェクトで使用するオブジェクトに適用することもできる。を送るようなコードを書くと
display
メッセージにid
という変数があれば、その変数にdisplay
メソッドを持つものを潜在的な受信者と呼びます。ダイナミックバインディング
関数呼び出しとメッセージの間には大きな違いがあります。関数とその精緻化はコンパイルされたコードで結合されます。しかし、メッセージとその受信者は、コードが実行され、メッセージが送信されるまで結合されません。したがって、メッセージに応答するために使用される特定のメソッドコールは、コンパイル時ではなく、実行時に決定することができます。
メッセージが送信されると、ランタイムメッセージルーチンがメッセージ内のレシーバーとメソッド名を調べます。メッセージの送信時に、実行時メッセージルーチンは受信者とメッセージ内のメソッド名を調べ、受信者にマッチするメソッド実装を探し出し、そのメソッドを "call"して受信者のインスタンス変数へのポインタを渡します。(このルーチンの詳細については Objective-Cランタイム・プログラミング・ガイド の中に メッセージング" Aセクション )
メッセージの動的なバインディングメソッドとポリモーフィックな性質は、オブジェクト指向プログラミングに強力なスケーラビリティを与えます。各オブジェクトは独自のメソッドを持っているので、Objective-Cの文は、メッセージを変えるのではなく、それを受け取るオブジェクトを変えることで、様々な結果を得ることができるのです。受信者をプログラム実行時に動的に決定することができる。ユーザーのアクションなどに応じて、受け手が判断できる。
アプリケーションキットをベースにしたアプリケーションを実行する場合( AppKit ) のコードでは、例えば、カット、コピー、ペーストなどのメニュー・コマンドからのメッセージを受信する必要があるオブジェクトをユーザーが決定します。メッセージは、現在のオプションを制御しているオブジェクトを見つけます。テキストを表示するために使用されるオブジェクト とスキャンした画像を表示するオブジェクト は、このメッセージをコピーしたときの反応が異なる。メッセージは実行時まで目的のメソッドを選択しないため(言い換えれば、メッセージにバインドされたメソッドは実行時にのみ実行されるため)、このような動作の違いにより、異なるメソッドを区別することができます。メッセージを送信するコードは、それらに注意を払う必要はありません。可能性を推測する必要さえないのです。アプリケーションのオブジェクトはすべて、チームメイトと同じようにメッセージの複製に反応することができます。
<スパン Objective-Cではダイナミックバインディングをさらに進めて、変数に送るメッセージを実行時に決定することもできる。これをどのように実装するかについては Objective-Cランタイム・プログラミング・ガイド の中に メッセージング(Messaging) のセクションで議論します。
ダイナミック・アプローチ・プログラムクラスおよびインスタンスメソッドの実装を提供するために、実行時に動的なメソッド配置を使用することができます。詳しくは Objective-Cランタイム・プログラミング・ガイド の ダイナミック・メソッド解決法
-
関連
-
[解決済み】Xcode 10 Error: 複数のコマンドが生成される
-
[解決済み] プロビジョニングプロファイルの作成に失敗しました
-
[解決済み] NSTimerでカウントダウンを作るには?
-
[解決済み] Xcode 9.2での「Warning: unable to build chain to self-signed root for signer(警告:自己署名ルートへのチェーンを構築できません)」警告。
-
[解決済み] macOS High Sierra にアップデートしてから、Xcode で「FIFinderSyncExtensionHost クラスは両方の ... に実装されています」という警告が表示されるようになった。
-
[解決済み] モジュールがmain.swift以外の場合、「トップレベルでは式が許可されない」と表示される
-
[解決済み] そのようなモジュール 'UIKit' はありません
-
[解決済み] AVAudioSession は AVFoundation フレームワークに存在しません。
-
[解決済み] Snow Leopard用Xcode:入手先
-
[解決済み] "pod init" で "-bash: pod: コマンドが見つかりません" というエラーが発生しました。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Xcodeです。mp3 ファイルをダウンロードする [終了しました] 。
-
[解決済み] Xcode Error メンバー 'dataTask(with:completionHandler:)' へのあいまいな参照 [重複].
-
[解決済み] Swift で、内部型であり、同じモジュールに存在するにもかかわらず、「未宣言の型を使用」する
-
[解決済み] Xcode 10にアップグレードした後の問題:ビルド入力ファイルが見つからない
-
[解決済み] Xcodeでカラーピッカーを開くにはどうしたらいいですか?
-
[解決済み] メモリ圧迫によるiOSのクラッシュをデバッグする方法
-
[解決済み] Xcode 開発者プロファイルをエクスポートして、別のMacでインポートする方法
-
[解決済み] Xcode - しかし... 私たちのアーカイブはどこ?
-
[解決済み] xcode-select active developer directory エラー
-
Xcodeの警告とエラー解消のまとめ