Objective-Cをれロから

Apple補品のプログラムを自分の人生で曞きたいず思う人は誰でも、新しいプログラミング蚀語であるObjective-Cを孊ばなければならないずきが来たす。 この幞せな瞬間が私を理解したした。 そしお、この蚀語の䞻な特城をよりよく芚えるために、私はあなたず共有するドキュメントを理解しながら私の考えを抂説するこずにしたした。



OOPの出珟の䞀般的な理論



蚘述されたコヌドずその移怍性を再利甚する問題により、プログラマヌは、それを敎理、構造化、および抜象化するこれたでにない方法を垞に探しおいたす。 これらの問題を解決するために、新しいプログラミングパラダむム、蚭蚈パタヌン、新しい蚀語、コンパむラヌおよびそれらの暙準ラむブラリ、゜フトりェアプラットフォヌム、フレヌムワヌクが䜜成されたす。 これは、サブプログラム手順のパラダむムが圢成され、CALL \ RETプロセッサ呜什ずスタックの助けを借りお実装された方法です実際、珟圚のコマンドに続くものではなく、実行スレッドを任意のアドレスに転送しおからリタヌンしたす。 次に、モゞュヌルパラダむム各ファむルは個別の翻蚳単䜍により、モゞュヌルのコンパむル、および実行可胜モゞュヌルぞのアセンブリ静的たたは動的の2段階の翻蚳が行われたした。



プロゞェクトのコヌド量の増加ずそれをサポヌトする難しさにより、1960幎代に新しいオブゞェクト指向プログラミングパラダむムが圢成され始め、プログラムはさらに小さなコンポヌネントデヌタ型に分割されたした。 その本質は、盞互にメッセヌゞを送信するこずによる゚ンティティオブゞェクトの盞互䜜甚にありたす。 各オブゞェクトは、プログラマヌによっお定矩されたデヌタ型いわゆるクラスの倉数です。 このような特別なナヌザヌデヌタ型クラスの定矩は、デヌタセット䞍倉匏、メンバヌの定矩ず、それらを提䟛するルヌチンセットメ゜ッドの2぀で構成されたす。









クラスは通垞、組み蟌み蚀語デヌタ型および/たたは他のクラスに基づいお、プログラマヌによっお定矩された型ずしおフォヌマットされたす。 オブゞェクト指向のパラダむムをサポヌトしないC蚀語の堎合、これは構造䜓である堎合がありたす。 ルヌチンのセットは通垞の関数ずしお実装され、少なくずも1぀のパラメヌタヌ凊理されるデヌタのセットぞのポむンタヌを必ず必芁ずしたす。



オブゞェクト指向のアプロヌチの䞻な利点は、継承ず呌ばれる、すでに蚘述されたクラス䞍倉匏ずメ゜ッドの远加、メ゜ッドの再定矩、基本クラスで定矩されたメ゜ッドの䜿甚に基づいお新しいクラスを䜜成できるこずでした。









メ゜ッドのセットは、䞍倉匏ず察話するためのむンタヌフェヌスです。 むンタヌフェむスを䜿甚せずにクラスデヌタを盎接倉曎できないこずは、カプセル化の原則を反映しおいたす。 この図は、クラスずそのオブゞェクトを瀺しおいたす。 float型の䞍倉匏xず、䞍倉匏の倀を返すむンタヌフェむスメ゜ッドdoubleXがありたす。



間違いなくそれに応答するオブゞェクトにメッセヌゞを送信する必芁がある぀たり、クラスオブゞェクトに実装したメ゜ッドを呌び出す必芁がありたすが、状況によっおは、このオブゞェクトの特定のクラスは䞍明です。 たずえば、Autoクラスのオブゞェクトぞのポむンタヌのリストの各芁玠にはMoveメッセヌゞを送信する必芁がありたすが、リストにはAutoクラスだけでなく、掟生継承FordおよびSubaruクラスぞのポむンタヌも含たれおいるこずがわかっおいたす。 これは、すべおのオブゞェクトがそのようなメッセヌゞを受信できるクラスの特定の階局から特定のメッセヌゞがオブゞェクトに送信されるず、このオブゞェクトはこの階局の基本クラスではなく、自身のクラスに埓っお反応するずいう事実にあるポリモヌフィズムの原理のおかげでのみ行うこずができたす。



オブゞェクト指向のアプロヌチをサポヌトする最初の蚀語はSimula67でした。 その埌、Smalltalkが登堎したした。 そしお、80幎代にC ++が圢になり始めたした-珟代のシステムプログラミングの䞻芁蚀語です。 90幎代の拡匵ず改善により、倚くのパラダむムずデザむンパタヌンが生成され、Objective-C蚀語を含むオブゞェクト指向アプロヌチの珟代のビゞョンに䞍可逆的な圱響を䞎えたした。



ちょっずした歎史



Objective-Cは、80幎代にSmalltalkに察するCの修正ずしお生たれたした。 さらに、この倉曎は、新しい構文構造ず特別なプリプロセッサコヌドを通過しお通垞のC関数呌び出しに倉換ずランタむムラむブラリこれらの凊理呌び出しを远加するこずで構成されおいたした。 したがっお、圓初、Objective-CはCのアドオンずしお認識されおいたした。ある意味では、これは䟝然ずしお圓おはたりたす。玔粋なCでプログラムを䜜成し、Objective-Cからいく぀かのコンストラクトを必芁に応じお远加できたす。それどころか、Objective-CのプログラムでCを自由に䜿甚できたす。 さらに、これはすべおC ++プログラムに適甚されたす。 1988幎、NeXTおよびそれ以降のAppleはObjective-Cのラむセンスを取埗し、そのためのコンパむラず暙準ラむブラリ基本的にSDKを䜜成したした。 1992幎、GNUプロゞェクトの開発者がOpenStepプロゞェクトに参加しお、蚀語ずコンパむラを改善したした。 それ以来、GCCはObjective-Cをサポヌトしおいたす。 NeXTを賌入した埌、AppleはSDKコンパむラ、ラむブラリ、IDEをさらなる開発の基瀎ずしたした。 コヌドのIDEはXcodeず呌ばれ、GUIの堎合はInterface Builderず呌ばれおいたした。 GUI開発甚のCocoaフレヌムワヌクだけでなくは、Objective-Cプログラムの最も重芁な開発環境です。



Objective-Cの機胜



Objective-Cモゞュヌルファむルの拡匵子は「.m」ですC ++ずObjective-Cの混合が䜿甚された堎合、拡匵子は「.mm」です。 ヘッダヌファむルは「.h」です。 Objective-Cで䜜成されたすべおのクラスオブゞェクトは、動的メモリに割り圓おる必芁がありたす。 したがっお、特に重芁なのはidタむプであり、これは任意のクラスのオブゞェクトぞのポむンタヌです基本的にvoid *。 NULLポむンタヌは、nil定数ず呌ばれたす。 したがっお、任意のクラスぞのポむンタヌをid型にキャストできたす。 問題がありたすidの䞋に隠れおいるオブゞェクトがどのクラスに属しおいるかをどのように知るのですか これは、特別な基本クラスNSObjectを継承するクラスのオブゞェクトに存圚するisa䞍倉匏のおかげで行われたすNSプレフィックスはNeXT Stepを衚したす。 isa䞍倉匏は予玄型Classに属したす。 このタむプのオブゞェクトを䜿甚するず、独自の基本クラスの名前、クラス䞍倉匏のセット、およびこのオブゞェクトが実装したすべおのメ゜ッドのプロトタむプずそのアドレスをセレクタヌのロヌカルリストを介しお芋぀けるこずができたす。 Cの予玄語ずは異なるすべおのObjective-Cの予玄語は、@で始たりたすたずえば、@ protocol、 selector 、 interface 。 通垞、限定されたスコヌプ@ private、 protected を持぀クラスの䞍倉匏の名前はアンダヌスコアで始たりたす。 Cocoaには、文字列甚の非垞に䟿利なNSStringクラスがありたす。 このクラスの文字列定数は、Cで通垞䜿甚される文字列定数「Hello world」ではなく、@「Hello world」ずしお蚘述されおいたす。 BOOL型本質的に笊号なしcharは、YESおよびNOの定数倀を取るこずができたす。 Objective-C固有のすべおの予玄語Cずは異なり、objc / objc.hヘッダヌファむルにありたすは以䞋のずおりです。



メッセヌゞング



オブゞェクトに䜕らかのメ゜ッドを匷制的に実行させるには、必芁なメ゜ッドず同じ名前のメッセヌゞを送信する必芁がありたす。 このようなメッセヌゞはメ゜ッドセレクタず呌ばれたす。 パッケヌゞの構文は次のずおりです。



[receiver method];
      
      











メッセヌゞでは、呌び出されたメ゜ッドにパラメヌタヌを枡すこずができたす。



 [receiver method: 20.0 : 30.0];
      
      





各パラメヌタヌの前にはコロンを付ける必芁がありたす。 コロンの数-非垞に倚くのパラメヌタヌ。 メ゜ッド名は、各コロンパラメヌタヌの埌に続けるこずができたす。



 [receiver methodWithFirstArgument: 10 andSecondArgument: 20];
      
      





匕数の数に制限のないメ゜ッドは、次の構文で呌び出されたす。



 [receiver undefinedNumberParameters: one, two, three, four, five, six, seven];
      
      





C関数ず同様に、メッセヌゞを送信するず、特定のおそらくvoid倀が返されたす。



 BOOL booleanValue; booleanValue = [reveiver method];
      
      





nilメッセヌゞを送信するず、メッセヌゞは消えたす。 順序付けされたメ゜ッドを実装しなかったクラスに属するオブゞェクトにメッセヌゞを送信するず、䟋倖が発生し、キャッチされない堎合、プログラム党䜓が蚈画倖の終了に぀ながりたす。 特定のオブゞェクトがメッセヌゞに応答するかどうかを確認するには、次のコヌドテンプレヌトを䜿甚できたす。



 if ([anObject respondsToSelector: @selector(myMethodWith2Argumets::)]) { //  [anObject myMethodWith2Argumetns: @”first” : @”second”]; } else { //      }
      
      







メッセヌゞングの仕組み



メッセヌゞの送信は、プロトタむプずずもにC関数でブロヌドキャストされたす。



 id objc_msgSend(id receiver, SEL method, ...);
      
      





実際、SELタむプはchar const *ずしお定矩されおいたすが、実行時にすべおのセレクタヌはグロヌバルセレクタヌテヌブルに埓っお敎数倀でむンデックス付けされるため、intずしお解釈する方が適切です。









レシヌバヌオブゞェクトのisa䞍倉匏を䜿甚するCocoaの基本であるFoundationフレヌムワヌクを䜿甚する堎合、すべおのクラスはNSObjectクラスを継承する必芁があるため、isaの存圚は避けられない、この関数はクラスセレクタヌのロヌカルリストをスキャンしお、このクラスのオブゞェクトがメ゜ッドメッセヌゞに応答するかどうかを刀断したす。 そのようなセレクタヌが芋぀かった堎合、制埡は、オブゞェクトIDその䞍倉匏ぞのポむンタヌず、セレクタヌの埌に指定されたobjc_msgSend関数のパラメヌタヌが枡されるクラスの察応するメ゜ッドに転送されたす。 メ゜ッドによっお返される倀は、メッセヌゞの送信結果ずしお返されたす。 レシヌバヌオブゞェクトにこのセレクタヌがない堎合、objc_msgSend関数はその基本クラスのセレクタヌのリストをスキャンしたす。









このスキヌムでは、呌び出し、たずえば



 [receiver ddObject: otherObject];
      
      





攟送先



 objc_msgSend(receiver, 12, otherObject);
      
      





グロヌバルセレクタテヌブル12では、文字列「addObject」に察応しおいるためです。 次に、objc_msgSend関数はレシヌバヌオブゞェクトのセレクタヌのリストを怜玢し、それを芋぀けおセレクタヌ12でメ゜ッドを実装するNSArrayクラスのオブゞェクトずする、次のタむプの呌び出しを行いたす。



 addObject(receiver, otherObject);
      
      







メ゜ッド宣蚀



クラス宣蚀の前のセクションのaddObjectメ゜ッドのプロトタむプが次のようになったこずに泚意しおください。



 - (void)addObject: (id)otherObject;
      
      





぀たり、必芁なパラメヌタヌは1぀だけでした。 ただし、メ゜ッドは特定のデヌタセットを凊理するルヌチンであるずいうオブゞェクト指向のパラダむムの原則に基づいお、メ゜ッドは凊理するデヌタのアドレスを枡す必芁がありたす。 したがっお、このようなパラメヌタは暗黙的にクラスメ゜ッドに枡されたす。 この远加パラメヌタヌに関するコンパむラヌは、メ゜ッドのプロトタむプの最初のマむナス "-"をクリアしたす。 そのようなメ゜ッド前にマむナス蚘号が付いおいるは、オブゞェクトたたはむンスタンスメ゜ッドず呌ばれたす。 あるクラスのオブゞェクトでのみ呌び出すこずができたす。 メ゜ッドの本䜓では、デヌタむンスタンスたたはメッセヌゞの送信先のオブゞェクトのアドレスぞのこのポむンタヌは予玄語selfC ++のこれに類䌌からアクセスでき、基本クラスむンスタンスぞのポむンタヌは予玄語superからアクセスできたす。 さらに、グロヌバルセレクタテヌブルのこのメ゜ッドのセレクタである暗黙のパラメヌタ_cmdもオブゞェクトメ゜ッドに枡されたす。 C ++プログラマヌの芳点から芋るず、Objective-Cのすべおのオブゞェクトメ゜ッドは、仮想キヌワヌドで宣蚀されおいるように芋え、垞に動的なポリモヌフィズムに埓いたす。



プロトタむプメ゜ッドの先頭にプラス蚘号「+」​​を付けるず、そのようなメ゜ッドはクラスメ゜ッドず芋なされ、もちろん、暗黙的なパラメヌタヌselfを受け入れたせんこれはC ++で静的メ゜ッドを宣蚀するのず䌌おいたす。 そしお、selfが指すオブゞェクトのisa䞍倉量がなければ、スヌパヌポむンタヌも確かに機胜したせん。

したがっお、メ゜ッドのプロトタむプは次のように宣蚀されたす。



 -|+ (<  >)  [ : (<  >) [ [] : (<  >)] 
 ]
      
      





䟋



 + (Class)class; + (id)alloc; - (id)init; - (void)addObject: (id)anObject; + (NSString *)stringWithCString: (const char*)aCString usingUncoding: (enum NSStringEncoding)encoding; - (NSString *)initStringWithFormat: (NSString *)format, 
;
      
      





メ゜ッドがオブゞェクトidタむプたたはクラスClassタむプを返す堎合、ネストされた呌び出し構文を䜿甚できたす。



 [myLabel setText: [[NSString stringWithString: @”Hello”] stringByAppendingString: @” world”]];
      
      





ここで、UIKitフレヌムワヌクのUILabelクラスのオブゞェクトは、文字列@” Hello world”に等しい䞍倉テキストの倀に蚭定されたす。 この文字列は、文字列@” Hello”ず@” world”を連結しお圢成されたす。 1぀目は、@” Hello”定数パラメヌタヌを䜿甚しおNSWithクラスにstringWithStringメッセヌゞを送信した結果です。 このような呌び出しは、パラメヌタヌ文字列で初期化されたNSStringクラスのオブゞェクトを返したす。 次に、@” world”パラメヌタヌを含むstringByAppendingStringメッセヌゞがこのオブゞェクトに送信されたす。 このメッセヌゞを送信した結果は、レシヌバオブゞェクトの倀ず文字列匕数の連結を含むNSStringクラスのオブゞェクトです。 このオブゞェクトは、パラメヌタヌずしおmyLabelオブゞェクトのsetTextメッセヌゞにも分類されたす。



クラス宣蚀



Complex.hファむルで単玔な耇玠数クラスを宣蚀したす。



 #import <Foundation/Foundation.h> // NSObject   NSString @interface Complex : NSObject { double _re; //    double _im; //    NSString *_format; //    description } - (id)initWithRe: (double)re andIm: (double)im; //  + (Complex *)complexWithRe: (double)re andIm: (double)im; //      - (Complex *)add: (Complex *)other; //   - (Complex *)sub: (Complex *)other; //   - (NSString *)format; //   _format - (void)setFormat: (NSString *)format; //  _format - (double)re; //        - (void)setRe: (double)re; - (double)im; - (void)setIm: (double)im; @end
      
      





ご芧のずおり、広告党䜓がキヌワヌドむンタヌフェむスずendで囲たれおいたす 。 最初のステップは、䞍倉匏を䞭括匧で宣蚀するこずです。 䞭括匧の倖偎では、メ゜ッドが宣蚀されたす。 説明メ゜ッドは、理由のためにクラス宣蚀から欠萜しおいたす。 実際には、deallocメ゜ッドやinitメ゜ッドず同様に、クラス定矩に存圚したす。 耇雑なクラスのオブゞェクトに説明メッセヌゞを送信する堎合、セレクタヌのロヌカルリストが考慮されたす。コンパむル埌、このオブゞェクトのクラスによっお実装され、むンタヌフェむス郚分で宣蚀されおいないすべおのメ゜ッドのセレクタヌがそこに到達したす。 ぀たり、init、description、deallocは絶察に正しく呌び出されたす。



オブゞェクトを䜜成する



すべおのオブゞェクトは動的メモリに分散されるため、オブゞェクトの䜜成は2段階で実行する必芁がありたす。1メモリ割り圓おallocメッセヌゞおよび2䞍倉匏の初期化クラスコンストラクタヌ。



 MyClass *myObject = [[MyClass alloc] init]; //  MyClass alloc          ,   init    myObject
      
      





オブゞェクトを䜜成したら、安党に䜿甚できたす。



 NSMutableArray *array = [[NSMutableArray alloc] init]; //   MyClass *myObject = [[MyClass alloc] init]; //  [myObject myMethod]; //   [array addObject: myObject]; //    MyClass *otherObject = [array getLastObject:]; //   ,      [otherObject myOtherMethod: YES]; //       BOOL
      
      





䞀郚のクラスには、独自のむンスタンスを1ステップですばやく䜜成するためのメ゜ッドがありたす。 このようなメ゜ッドはクラスのメ゜ッドであり、そのクラスのオブゞェクトぞのポむンタヌを返したす。通垞、その名前はクラス自䜓の名前で始たりたす。 たずえば、メ゜ッド



 + (NSString *)stringWithCString: (char const *)string encoding: (NSStringEncoding)encoding;
      
      





allocおよびinit呌び出しを行わずに、察応する行で終了れロで初期化された既補の文字列を返したす。



 NSString *myString = [NSString stringWithCString: “Bla-bla-bla” encoding: NSASCIIStringEncoding];
      
      







オブゞェクトの寿呜



オブゞェクトぞのポむンタがスコヌプを超えるず、割り圓おられたメモリは回埩䞍胜なほど倱われもちろん、そのオブゞェクトぞの最埌のポむンタでない限り、リヌクが発生したす。 このような望たしくない結果を回避するために、Objective-Cはリ゜ヌスぞのリンクをカりントするずいうパラダむムをサポヌトしおいたす。 したがっお、各オブゞェクトには、それぞのポむンタヌの数を瀺す敎数カりンタヌがありたす。 このカりンタヌがれロに達するず、このオブゞェクトに割り圓おられたメモリがシステムに返されたす。 allocクラスのメ゜ッドを呌び出した埌、このカりンタヌは1に等しくなりたす。 その倀を増やすには、オブゞェクトにメッセヌゞを送信する必芁があり、保持し、削枛する必芁がありたす。 これらのメ゜ッドはすべおNSObjectによっお実装されおおり、どのクラスも確実に継承したす。 NSStringクラスの静的オブゞェクトのカりンタヌ倀@ "I am a string"などが-1、぀たり可胜な最倧倀であるこずに泚意しおください。 カりンタヌの䜿甚䟋を次に瀺したす。



 id anObject = [SomeClass alloc]; //  == 1 [anObject init]; //    [anObject reatin]; //   (  == 2) [anObject release]; // (  == 1     ) [anObject release]; // ,   1         
      
      





initの実装は非垞に重芁です。 これはクラスコンストラクタヌです。 コンストラクタヌは、idを返し、名前が垞にinitで始たるずいう点で異なり、デフォルトのコンストラクタヌはinitのみです。 コンストラクタのスキヌムは、ほが次のずおりです。



 - (id)init { self = [super init]; //     //   if (self) //        //    ,      nil { //       } return self; //    }
      
      





クラスの型の2぀のメンバヌず1぀の敎数䞍倉匏を持぀クラスの兞型的な特殊なデフォルトではないコンストラクタヌを次に瀺したす。



 - (id)initWithInt: (int)number { if (self = [super init]) { _myMember1 = [[SomeClass alloc] init]; //  :  ,    _myMember2 = [[SomeClass alloc] init]; _myIntMember = number; //     //   } return self; }
      
      





NSObjectのリリヌスおよび保持の実装は、むデオロギヌ的にほが次のずおりであり、参照カりンタヌ䞍倉匏ぞのアクセスがないため、掟生クラスで再定矩する必芁はありたせん。



 - (void)retain { [_internalLock lock]; //   _referenceCounter++; //  _referenceCounter –    [_internalLock unlock]; } - (void)release { [_internalLock lock]; _referenceCounter--; //  if (!_referenceCounter) //    { [_internalLock unlock]; [self dealloc]; // ,    (  ) } [_internalLock unlock]; }
      
      





぀たり、deallocメッセヌゞはオブゞェクト自䜓に送信されたす。このメ゜ッドの実装では、必芁に応じお、䞍倉匏のカりンタヌを枛らし、同様のメッセヌゞを基本クラスのオブゞェクトに枡しお、同じこずができるようにしたす。 明らかに、NSObjectにdeallocメ゜ッドを実装するず、オブゞェクトに割り圓おられたメモリが解攟されたす。 通垞、䞀郚のクラスのdeallocは次のようになりたす。



 - (void)dealloc { [_myMember1 release]; //    [_myMember2 release]; //     //[_myIntMember release];   , ..           [super dealloc]; //c   ,     }
      
      







アクセス方法



メ゜ッドからオブゞェクトのアドレスを返すずき、たたは仮パラメヌタヌを䜿甚しお䞍倉匏を初期化するずき、参照カりントの正しい䜜業は非垞に重芁です。 通垞、このようなこずは、オブゞェクトの䞍倉匏を返し、蚭定する、いわゆるアクセスメ゜ッドによっお行われたす。 䞍倉匏だけでなく䞍倉匏の倀を返すメ゜ッド、およびその倀を蚭定するメ゜ッドの名前を指定するこずは慣習です。



 - (void)setRe: (double)re { _re = re; }
      
      





_re䞍倉匏は組み蟌み型に属しおいるため、倀を倉曎しおも問題はありたせん。 ただし、䞍倉匏が特定のクラスのオブゞェクトである堎合、参照カりンタヌを考慮する必芁があるため、単玔な割り圓おが䞍可欠です。 この問題を解決するには、次の3぀の方法が䜿甚されたす。



 //,      [label setText: @”Hello world”]; //  text // label     NSString * //  setText   UILabel ( №1) - (void)setText: (NSString *)text { [text retain]; //      [_text release]; //       _text _text = text; //    } //  setText   UILabel ( №2) - (void)setText: (NSString *)text { if (_text != text) //c    { [_text release]; //     //  _text _text = [text retain]; //   //       } } //  setText   UILabel ( №3 – ) - (void)setText: (NSString *)text { if (_text != text) { [_text autorelease]; // e   // _text    _text = [text retain]; //   //       } }
      
      





オプション3は珟圚のセルフロヌディングプヌルを詰たらせるため、あたり成功したせんが、これは通垞あたり望たしくありたせん次のセクションを参照。

䞍倉匏の倀を読み取るためのアクセス方法は、垞に非垞に簡単です。



 - (NSString *)text { return _text; }
      
      







プログラムスレッドのセルフロヌディングプヌル



ここで、メ゜ッド内で䜜成されたオブゞェクトをメ゜ッドから返しおみたしょう。



 -(NSString *)sayHelloToName: (NSString *)name withSurname: (NSString *)surname { NSString *retString = [[NSString alloc] initWithFormat: @”%@ %@!”, name, surname]; //      return retString; }
      
      





フォヌマット文字列はC蚀語暙準に準拠しおいたすが、IDタむプを指定する必芁がある堎合は、@フォヌマット指定子が䜿甚されたす。 フォヌマットを解析する方法は、どの文字をidに眮き換えるかをどのように理解したすか 指定されたオブゞェクトの説明の説明メ゜ッドを返すものに単玔に眮き換えたす。 このメ゜ッドは、元々NSObjectクラスに察しお宣蚀されおいたした。 NSStringは、文字列の内容を出力するように再定矩したした。 再定矩するこずにより、任意のオブゞェクトがその文字列コンテンツを衚すこずができたす。 たずえば、double型の2぀の䞍倉匏を持぀耇玠数のクラスはこれを実行できたす。



 - (NSString *)description { return [NSString stringWithFormat: @”re: %lf im: %lf”, _re, _im]; //  @“re: 1.0 im: 2.5”  _re == 1.0  _im == 2.5 }
      
      





sayHelloToNamewithSurnameメ゜ッドが実行されるず、返されたオブゞェクトが凊理埌にリリヌスメッセヌゞを送信する必芁があるこずを呌び出し偎コヌドが認識しおいない可胜性が高いため、メモリリヌクが必ず発生したす。 圌がそれをするこずを掚枬したずしおも、ポむンタヌがオブゞェクトの䞍倉匏に戻された可胜性がありたす。これは、その砎壊が深刻な結果を䌎うこずを意味したす。 ナヌザヌコヌドがオブゞェクトを解攟するこずをたったく考えないように、将来オブゞェクトの自己解攟のためのメカニズムが必芁です。 この問題は、NSAutoreleasePoolクラスのオブゞェクトを䜿甚しお解決されたす-NS



このクラスのオブゞェクトを䜜成した埌、それ以降に䜜成されたすべおのオブゞェクトに自動解攟メッセヌゞを送信できたす。 この堎合、このオブゞェクトは珟圚の最埌に䜜成されたセルフペヌゞプヌルに配眮されたす。 特定のプヌルがリリヌスメッセヌゞを受信するず、すべおのオブゞェクトに同じメッセヌゞを送信し、参照カりントを枛らしたす基本的には砎棄したす。 そのように。 自己ロヌドプヌルに配眮されたオブゞェクトは、プヌルの存続期間䞭ずっずメモリを䜿甚し続けたす。 これは小さな䞀時オブゞェクトには䟿利ですが、時間が経぀ずかなりの量のメモリを消費する可胜性がありたす。 したがっお、自己ロヌドプヌルに送信される倚数の䞀時オブゞェクトを生成できるルヌプは、ロヌカルネストされたプヌルでフレヌム化するこずをお勧めしたす。



Cocoaを䜿甚するプログラムのスレッドは、最初に他のオブゞェクトを䜜成する前にNSAutoreleasePoolクラスのオブゞェクトを䜜成し、最埌に他のすべおのオブゞェクトを砎棄した埌砎棄する必芁がありたす。 Cocoaフレヌムワヌクを䜿甚する堎合、Objective-Cプログラムのメむンスレッドであるmain関数は垞に次のようになりたす。



 int main(int argc, char *argv[]) //    main() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // ,     int retVal; //    [pool drain]; //    ,     autorelease return retVal; }
      
      





そしお、正しいsayHelloToNamewithSurnameメ゜ッドは次のようになりたす。



 -(NSString *)sayHelloToName: (NSString *)name withSurname: (NSString *)surname { NSString *retString = [[NSString alloc] initWithFormat: @”%@ %@!”, name, surname]; //      [retString autorelease]; //  ,  retString     return retString; }
      
      





ちなみに、セルフペヌゞプヌルのドレむンメ゜ッドはリリヌスず䌌おいたすが、唯䞀の違いは、自己ず含たれおいるすべおのオブゞェクトを解攟するこずに加えお、ガベヌゞコレクタヌにゲヌムに入るためのヒントを䞎えるこずです。 ただし、iOSにはガベヌゞコレクションがないため、これはMac OS 10.4以降にのみ関連したす。



クラス定矩



次に、Complexクラスのメ゜ッドの定矩を含むComplex.mファむルを怜蚎したす。



 #import “Complex.h” @implementation Complex - (id)init { return [self initWithRe: 0.0 andIm: 0.0]; } - (id)initWithRe: (double)re andIm: (double)im { if (self = [super init]) { _re = re; _im = im; _format = @”re: %.1lf im: %.1lf”; //    } } + (Complex *)complexWithRe: (double)re andIm: (double)im { return [[[Complex alloc] initWithRe: re andIm: im] autorelease]; } - (Complex *)add: (Complex *)other { return [[Complex alloc] initWithRe: _re + other->_re andIm: _im + other->_im]; } - (Complex *)sub: (Complex *)other { return [[Complex alloc] initWithRe: _re – other->_re andIm: _im – other->_im]; } - (NSString *)format { return _format; } - (void)setFormat: (NSString *)format {//    - [format retain]; [_format release]; _format = format; } - (double)re { return _re; } - (void)setRe: (double)re { _re = re; } - (double)im { return _im; } - (void)setIm: (double)im { _im = im; } - (NSString *)description {//    return [NSString stringWithFormat: _format, _re, _im]; } - (void)dealloc { [_format release]; //    dealloc [super dealloc]; } @end
      
      





デフォルトのコンストラクタヌは、特定の初期パラメヌタヌで特殊なコンストラクタヌを呌び出したす。 complexWithReandImメ゜ッドは、珟圚の自己読み蟌みプヌルにあるComplexクラスの初期化されたオブゞェクトを返したす。 descriptionメ゜ッドも同じこずを行い、NSStringクラスのオブゞェクトを返したす。 以䞋に、Complexクラスを䜿甚するプログラムの䟋を瀺したす。



 #import “Complex.h” #import <stdio.h> // printf() int main() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; Complex *num1 = [[Complex alloc] init]; //0.0+0.0*i Complex *num2 = [[Complex alloc] initWithRe: 1.5 andIm: -2]; //1.5-2.0*i Complex *num3 = [Complex complexWithRe: 5 andIm: 7]; //5.0+7.0*i printf(“%s\n”, [[num2 description] cStringUsingEncoding: NSASCIIStringEncoding]); //> re: 1.5 im: -2.0 printf(“%s\n”, [[[num2 add: num3] description] cStringUsingEncoding: NSASCIIStringEncoding]); //> re: 6.5 im: 5.0 [num1 setRe: [num2 re]]; // _re  num1   num2 [num1 setIm: [num3 im]]; // _im  num1   num3 [num1 setFormat: @”%.2lf+%.2lf*i”]; //    num1 printf(“%s\n”, [[num1 description] cStringUsingEncoding: NSASCIIStringEncoding]); //> 1.50+7.00*i [num1 release]; [num2 release]; //[num3 release];  , ..      [pool drain]; return 0; }
      
      







カテゎリず拡倧



すでに蚘述されおいるおよびコンパむルされおいる可胜性のあるクラスに継承なしでいく぀かのメ゜ッドを再定矩する必芁がある堎合、カテゎリを䜿甚するず、倚くの劎力なしでこれを実行できたす。



 // “CategorizedComplex.h” #import “Complex.h” @interfce Complex (CategorizedComplex) - (Complex *)mul: (Complex *)other; - (Complex *)div: (Complex *)other; @end // “CategorizedComplex.m” #import “CategorizedComplex.h” @implementation Complex (CategorizedComplex) - (Complex *)mul: (Complex *)other { return [Complex complexWithRe: _re * other->_re - _im * other->_im andIm: _re * other->_im + _im * other->_re]; } - (Complex *)div: (Complex *)other { double retRe, retIm, denominator; denominator = other->_re * other->_re + other->_im * other->_im; if (!denominator) return nil; retRe = (_re * other->_re + _im * other->_im) / denominator; retIm = (_im * other->_re - _re * other->_im) / denominator; return [Complex complexWithRe: retRe andIm: retIm]; } @end
      
      





そしお、あなたはこのようにそれを䜿甚するこずができたす



 CategorizdComplex *num1 = [[CategorizedComplex alloc] initWithRe: 1 andIm: 999]; Complex *num2 = [Complex complexWithRe: 0 andIm: 0]; CategorizedComplex *num3 = [num1 div: num2]; //num3 == nil
      
      





拡匵機胜は、名前のないカテゎリずしお優れたサヌビスを提䟛したす。



 // “CategorizedComplex.m” #import “CategorizedComplex.h” @interface Complex () - (void)zeroComplex; //     @end @implementation Complex - (void)zeroComplex //       { _re = 0; _im = 0; } @end
      
      







プロトコル



Objective-Cプロトコルは、必芁に応じお任意のクラスすべおのメ゜ッドがvirtual ... = 0指定子で宣蚀されおいるC ++のクラスのアナログによっお実装できるメ゜ッドのグルヌプの正匏な宣蚀です。バヌゞョン2.0では、プロトコルメ゜ッド@required指定子、サむレントず芋なされるおよび遞択@optional指定子が必芁になる堎合がありたす。クラスが必芁なプロトコルメ゜ッドを実装しおいる堎合、このプロトコルをサポヌトするクラスず呌ばれたす。プロトコルずそれをサポヌトするクラスは次のように宣蚀されたす



 @protocol MyPrinterProtocol @required - (void)print; - (BOOL)switchedOn; @optional - (void)loadPapaer: (int)numberOfPages; @end @interface MyPrinter : NSObject <MyPrinterProtocol> // MyPrinter   MyPrinterProtocol { BOOL _state; int _numberOfPages; } - (id)initWithState: (BOOL)state andPagesCount: (int)pages; - (BOOL)state; @end
      
      





MyPrinterクラスのオブゞェクトは、printメッセヌゞずswitchOnメッセヌゞの送信を保蚌できたす。respondsToSelectorを確認した埌、loadPaperメッセヌゞを送信できたす。たずえば、同じ名前のメ゜ッドの定矩が実装に存圚する必芁がありたす。プロトコルをサポヌトするクラスオブゞェクトの宣蚀は次のずおりです。



 MyPrinter *printer; id anotherPrinter = [[MyPrinter alloc] init]; [anotherPrinter print]; //       
      
      





さらに、1぀のクラスで耇数のプロトコルを満たすこずができたす。これを行うには、クラス宣蚀の山括匧内にコンマで区切っおリストしたす。



 @interface MyPrinter : NSObject <MyPrinterProtocol, OtherProtocol>
      
      





そしお、あるプロトコルに察応する未知のクラスidのオブゞェクトを宣蚀するには、次のように曞きたす。



 id <MyPrinterProtocol> somePrinter;
      
      





䟋倖



゚ラヌ凊理には、䞻に2぀のアプロヌチがありたす。グロヌバルステヌタス倉数は、その倀によっお前の操䜜の成功を通知し、䟋倖を生成したす。䞡方の本質は、゚ラヌが発生したコヌドが、それを呌び出したコヌドがそれを解決できるこずを望んでいるため、可胜な限り詳现な状況を報告しお制埡を返すこずです。 Objective-Cは、これらのアプロヌチの䞡方をサポヌトしおいたす。



䟋倖は、あるクラスのオブゞェクトです。圌は圌のタむプによっおも状況に関するいく぀かの情報を持っおいたす。䟿宜䞊、Cocoaには、2぀のNSStringオブゞェクトず任意のクラスid型の1぀のオブゞェクトで初期化できるNSExceptionクラスがありたす。



 - (id)initWitnName: (NSString *)name reason: (NSString *)reason userInfo: (id)userInfo;
      
      





@throw挔算子を䜿甚しお、䟋倖をスロヌしお、コヌルスタックプロモヌションメカニズムを開始できたす。生成された䟋倖をキャッチするには、コヌドの生成可胜な郚分を、tryずいうタむトルの特別なブロックで囲む必芁がありたすこのようなブロックはネストできたす。そしお、このブロックの埌に、タむトルcatchを持぀ブロックを配眮したす。括匧内は、申し立おられた䟋倖のタむプを瀺したす。tryブロックの埌にいく぀かのcatchブロックが存圚する堎合がありたす。䟋倖がスロヌされた埌、コントロヌルはスタックをスピンし、tryブロックを終了し、すべおのcatchブロックを順番にチェックしお、そのcatchブロックに入りたす、䞭括匧内に、䟋倖の型が暗黙的にキャストされる型がありたす完党䞀臎、基本クラスたたはidぞのポむンタヌ。タむプ䟋倖がどのcatchブロックずも䞀臎しない堎合、コントロヌルはスタックし続けたす。tryヘッダヌのあるブロックの埌にfinallyヘッダヌのあるブロックがある堎合、tryブロックで䟋倖が発生したかおよびcatchブロックが凊理されたか、最埌の呜什が実行されたかに関係なく、制埡が枡されたす。以䞋は、䟋倖が発生するfillメ゜ッドでCupクラスのオブゞェクトを操䜜する䟋です。



 Cup *cup = [[Cup alloc] init]; @try { [cup fill]; // fill    NSException } @catch (NSException *exception) {//     NSLog NSLog(@"main: Caught %@: %@", [exception name], [exception reason]); } @finally //  @try    { [cup release]; }
      
      





finallyブロックでは、tryブロックで割り圓おられたリ゜ヌスを解攟するず䟿利ですが、生成された䟋倖のために解攟されたせん。



プロパティ



Objective-C 2.0の堎合、Complexクラスの実装は明らかに冗長です。アクセスメ゜ッドが倚すぎるため、その定矩は継続的なルヌチンです。プロパティを䜿甚しお曞き換えたす



 // “Complex.h” #import <Foundation/Foundation.h> // NSObject   NSString @interface Complex : NSObject { double _re; //    double _im; //    NSString *_format; //    description } - (id)initWithRe: (double)re andIm: (double)im; + (Complex *)complexWithRe: (double)re andIm: (double)im; - (Complex *)add: (Complex *)other; //   - (Complex *)sub: (Complex *)other; //   @property (nonatomic, retain) NSString *format; //   @property (nonatomic, assign) double re; //   @property (nonatomic, assign) double im; @end // “Complex.m” #import “Complex.h” @implementation Complex @synthesize format = _format; //   @synthesize re = _re; //    @synthesize im = _im; //      - (id)init { return [self initWithRe: 0.0 andIm: 0.0]; } - (id)initWithRe: (double)re andIm: (double)im { if (self = [super init]) { _re = re; _im = im; _format = @”re: %.1lf im: %.1lf”; //    } } + (Complex *)complexWithRe: (double)re andIm: (double)im { return [[[Complex alloc] initWithRe: re andIm: im] autorelease]; } - (Complex *)add: (Complex *)other { return [[Complex alloc] initWithRe: _re + other.re andIm: _im + other.im]; //  re  im } - (Complex *)sub: (Complex *)other { return [[Complex alloc] initWithRe: _re – other.re andIm: _im – other.im]; //  re  im } @end
      
      





プロパティは、ドット挔算子「。」を介したオブゞェクトぞのポむンタヌを介しおアクセス可胜な名前です。オブゞェクトの䞍倉匏を取埗たたは蚭定するには、アクセサメ゜ッドの代わりにプロパティを䜿甚したす。プロパティを宣蚀するずき、プロパティによっお生成されたアクセスメ゜ッドの機胜を蚘述するいく぀かのパラメヌタヌが指定されたす。

Complexクラスの定矩では、アクセスメ゜ッドを手動で蚘述する必芁はありたせん。これらはコンパむラヌによっお生成され、以前のものず同䞀になりたす。



頑匵っお



All Articles