1. ホーム
  2. xcode

Objective-Cプログラミング言語公式文書 (II) - オブジェクト、クラス、メッセージ

2022-02-23 04:23:19

<スパン 声明 この文書は、参照を描画するために同胞の開発を促進するために、手の翻訳の唯一の個人的な学習プロセスです。あなたは、翻訳が良いか、または所定の位置にないと感じた場合は、訂正することを歓迎し、速やかに修正を行います。



私のプログラミング環境です。

IDEです。XCODE 4.3.1

OS:MAC OS X 10.7.4

記事の翻訳元:http://developer.apple.com/

オブジェクト、クラス、メッセージング

この章では、Objective-Cで使用され、実装されているオブジェクト、クラス、メッセージングの基本を紹介します。また、ランタイム環境についても少し紹介します。

ランタイムシステム


<スパン <スパン Objective-C言語は、コンパイル時、リンク時、実行時までの判断を可能な限り先送りしています。オブジェクトの生成やメソッドの呼び出しなどの操作は、可能な限り動的に行います。 そのため、この言語にはコンパイラだけでなく、コンパイルされたコードを実行するためのランタイムシステムも必要である。Objective-Cの場合、ランタイムシステムはオペレーティングシステムに近い役割を果たす。通常、ランタイム環境と直接やりとりする必要はない。ランタイムが提供する機能を理解するために Objective-Cランタイム・プログラミング・ガイド .
<スパン

オブジェクト
オブジェクト指向プログラミングは、オブジェクトを中心に構築されています。オブジェクトに関連するデータは、そのデータに対する特定の操作によって影響を受けることができます。 Objective-Cでは、オブジェクトのクラスが指定されていない場合でも、オブジェクト変数を識別するデータ型が用意されています。


<スパン

オブジェクトの基本

<スパン オブジェクト指向プログラミングは、オブジェクトを中心に構築されています。オブジェクトはデータに関連しており、ある操作によってそのデータに影響を与えることができる。つまり Objective-Cでは、これらの操作をオブジェクトのメソッドと呼びます。メソッドによって影響を受けるデータは、そのインスタンス変数です。(他の文脈では、インスタンス変数やメンバ変数を指すこともある)。基本的に、オブジェクトはデータ構造(インスタンス変数)と一連の処理(メソッド)を自身のプログラミングユニットに束ねる。
<スパン <スパン <スパン
<スパン <スパン Objective-Cでは、オブジェクトのインスタンス変数が顕在化の本質であり、通常はオブジェクトのメソッドを通じてのみオブジェクトの状態にアクセスできます(サブクラスや他のオブジェクトがメンバー変数に直接アクセスできるかどうかは、domain指示文を用いて指定できます)。オブジェクトに関する情報を得たい他の人のために、上記の情報を提供するメソッドを用意する必要があります。例えば、矩形はそのサイズと位置を取得するメソッドを持つべきです。
<スパン <スパン <スパン
<スパン <スパン <スパン もっと言うと、オブジェクトは私たちが設計したメソッドしか見ていないのです。他のオブジェクトのために設計されたメソッドを間違って実行することはできない。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などの名前付き引数やキーワード引数を使用する言語とは異なる構造になっています。

    <テーブル
    def func(a, b, NeatMode=SuperNeat, Thing=DefaultThing):
    
    
        pass
    
    
    このPythonの例では  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*) , a float ,   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  メソッドは引数を取らないので、やはり

    otherRect
    
    原色が見つかり、返される。各メソッドは、引数として宣言することなく、Receiver とそのインスタンス変数を受け取ります。

    この規約により、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ランタイム・プログラミング・ガイド  の ダイナミック・メソッド解決法