Objective-C
出典: フリー百科事典『ウィキペディア(Wikipedia)』
パラダイム: | オブジェクト指向プログラミング |
---|---|
設計者: | Brad Cox |
型付け: | 弱い動的型付け |
主な処理系: | Apple版、GNU版 |
影響を受けた言語: | Smalltalk、C言語 |
影響を与えた言語: | Java |
プラットフォーム: | Mac OS X他 |
Objective-C(オブジェクティブ シー)はプログラミング言語の一種。C言語をベースにSmalltalk型のオブジェクト指向機能を持たせた上位互換言語。
Objective-CはNeXT、Mac OS XのOSに標準付属する公式開発言語である。OS Xのパッケージ版に開発環境がCDで付属するほか、ユーザ登録をすれば無償でダウンロードできる。(Xcodeの項目参照)
目次 |
[編集] 概要
Objective-CはCを拡張してオブジェクト指向を可能にしたというよりは、Cで書かれたオブジェクト指向システムを制御しやすいようにマクロ的な拡張を施した言語である。従ってbetter Cに進んだC++と異なり、C & Object Systemという考え方であり、ある意味二つの言語が混在した状態にある。プログラマは問題領域に合わせて双方を使い分けることができるため、お互いの利点を活かしやすいのが特徴である。
言語全体としてはCの完全上位互換であり、if/for/whileなどの制御文や、intなどのスカラー型、関数記法、宣言・代入といった基本的な文法はCに準拠する。
一方オブジェクトシステムはSmalltalkの概念をほぼそのまま借用したもので、動的型のクラス型オブジェクト指向ランタイムを持ち、メッセージパッシングにより動作する。このことからしばしば「インラインでCの書けるSmalltalk」または「インラインでSmalltalkの書けるC」などと呼ばれる。
最大の特徴はオブジェクトシステムが完全に動的という点で、実行時のクラス拡張、オブジェクト汎用型idの導入により型によらない動的配列・辞書など、インタプリタに近い記述力をもつことである。実際にコードそのものはネイティブコンパイルされるものの、動作原理はほぼインタプリタに近く、コンパイラ型言語としては稀な柔軟性を発揮する。
従ってC側から見れば一種のスクリプトインタプリタが乗っているような状態であり、逆にオブジェクトシステムからはOS機能や膨大なC言語資源を直接利用可能なインターフェースが備わっているといえる。また仮想マシンを持たずに済むため、取り回しも良い。Objective-C特有のこの形態は双方のメリットが明確で、実用面での使い勝手が非常に優れている。この特性に着目したのがNEXTSTEPで、UNIXとの互換性と先進的なオブジェクト指向環境の両立に成功し、その後のOS設計に大きな影響を与えることとなった。
後続言語への影響としては、特にJavaの基礎設計にその姿を見る事ができる(SunがOPENSTEPに関わっていた事と関係がある)。
クラス | 単一継承+インタフェース多重継承(プロトコル) 通常はルートクラスから継承 |
---|---|
オブジェクトシステム | 動的束縛、メタクラスを持つ |
型 | 動的型+見た目の静的型のハイブリッド |
実行速度 | コードはCと同等のネイティブコンパイル、メソッド呼び出しは動的ディスパッチを行なうのでやや遅延する。平均してC/C++よりは遅く、中間コード型言語(Javaなど)より数倍する程度といわれる。ただし、クリティカルな部分はいつでもCに展開できるため、実行速度が問題になる事はまずない。 |
その他 | オブジェクトはポインタ互換、Cのスカラー型はオブジェクトではない |
[編集] 基本的な構文
[編集] メソッド呼びだし
C++とは異なり、オブジェクトのメソッド呼びだしには新たな構文が導入されている。メソッド呼びだしは実行時のメッセージパッシングであり、その時渡されるメッセージ値をセレクタという。特徴的なのはSmalltalk同様キーワード引数形式をとることで、セレクタ名と引数値が交互に並んだ形態になる。なおSmalltalkにはあるカスケード式(一つのオブジェクトに続けてメッセージを送る)はない。
// メッセージの送信 // 単項メッセージ [receiver msg]; // 引数付きメッセージ。この場合「msg:with:」でセレクタ一つ val = [receiver msg: arg1 with: arg2]; // メッセージの入れ子 val = [obj1 msg: [obj2 msg]];
[編集] クラス定義
Objective-Cのクラスは定義部と実装部に分かれており、通常定義部を.hファイル、実装部を.mファイルに記述する。後述のカテゴリによりクラス定義を複数のパートに分割できる。
// クラスの定義 @interface MyObject : NSObject { int val; id obj; } + (void)classMethod:(id)arg; // クラスメソッド - (id)method:(NSObject*)arg1 with:(int)arg2; // インスタンスメソッド。arg1は型付き @end
// 実装 @implementation MyObject + (void)classMethod:(id)arg { // some operation } - (id)method:(NSObject*)arg1 with:(int)args2 { /// return obj; } // 典型的なinit - (id)init { self = [super init]; // スーパークラスの呼びだし if(self != nil) { val = 0; obj = nil; } return self; } @end
メソッドにはクラスメソッドとインスタンスメソッドがあり、それぞれ接頭辞+及び-により区別される。メソッド呼び出しの際、クラスメソッドはクラスオブジェクトに、インスタンスメソッドは各インスタンスに送信される。
いわゆるコンストラクタは存在しない。慣習として新規オブジェクトの生成は+allocで、初期化は-initで行われるが、プログラマが自由に別の特殊化したメソッドを定義することが可能であり、初期化中に別の初期化メソッドを呼びだす場合もある。一方デストラクタ(ファイナライザ)に相当するものは-dealloc、またはガベージコレクション使用時の-finalizeで、これらのメソッドはオブジェクトの破壊時に必ず呼び出される。
selfは特殊な変数で、メソッドの実行時にレシーバとして渡される。代入も可能であり、-init等でスーパークラスの実装で自分自身を初期化し、正しい値が返った時のみ継続して初期化を行なうなどに利用される。
オブジェクトの型はオブジェクトを特定のクラスに制限したい時に用いられる。ただしこれはソースコードでのみ意味を持ち、実行レベルでは全てidとして扱われる。また型付きのオブジェクトはインスタンス変数を構造体互換でアクセスできる。保護レベルはpublic(フリー)、protected(継承クラスのみ)、private(同一クラスのみ)があり、デフォルトはprotectedである。ただメモリ管理の一貫性などの理由から、ほとんどの場合アクセサを用いる。
[編集] 特徴
[編集] リフレクション
Objective-Cのオブジェクトは全て自分自身に関する定義情報を保持しており、実行時に利用する事ができる。
[編集] リフレクションの一部
- (BOOL)respondsToSelector:(SEL)aSel; - (BOOL)isKindOfClass:(Class)cls;
[編集] 転送
実装系によるが、存在しないメソッドを呼びだした際、例外を発生する前にそれを他のオブジェクトに転送するチャンスが与えられる。method forwardingと呼ばれる。
[編集] 転送の例
Appleのランタイムでは、セレクタに対応する引数情報と転送処理の二つの過程を経て行われる。
// NSMethodSignatureはメソッドの引数の数や型情報を表すオブジェクト // Objective-Cのメソッドはスカラー型をとるC関数互換なので正確なスタック情報が必要となる - (NSMethodSignature*)methodSignatureForSelector:(SEL)sel { id signature = [otherObj methodSignatureForSelector: sel]; return signature; } // NSInvocationはターゲットと引数を持ち、返値を受け取るオブジェクト // 元のターゲットの代わりに別のターゲットで実行を行なうとあたかもそのオブジェクトにメッセージが送られたかのように動作する - (void)forwardInvocation:(NSInvocation*)invocation { SEL aSel = [invocation selector]; if([otherObj respondsToSelector: aSel]) [invocation invokeWithTarget: otherObj]; else [self doseNotRecognizeSelector: aSel]; }
[編集] プロトコル
プロトコルはクラスのメソッドインターフェースを規定する機構である。元々はNeXTワークステーション上で分散オブジェクトシステムを構成する際、リモートオブジェクトの通信効率を上げるために導入された。
プロトコルに準拠するクラスは定義されたメソッドを全て実装しなければならない。また、プロトコルは多重継承を許す。
プロトコルの例 // プロトコルを定義する @protocol MyProtocol <NSObject, NSCopying> - (void)methodForRespond; @end // プロトコルを導入する @interface MyObject <MyProtocol> ... @end
類似した機構に実装をオプションにできるinformalプロトコルがある。これは後述のカテゴリのうち、インターフェース定義のみを利用する方法で、利用側は実装状態をリフレクションで調査して正当な場合のみ呼びだす。
// ここでは「NSObjectにはtransferAcceptable:が定義されている」と宣言している // 実際には対応する実装を用意する義務がないため、NSObjectを継承したオブジェクトがそれを行なった場合のみ利用できる @interface NSObject (OptionalMethods) - (BOOL)transferAcceptable:(id)obj; @end - (void)method { id val,obj; ... if([obj respondsToSelector: @selector(transferAcceptable:)]) [obj transferAcceptable: val]; ... }
[編集] カテゴリ
カテゴリはメソッドのコレクションを定義して、クラス定義後に追加オーバーライドを行なう機構。
特徴的なのは、メソッドのオーバーライドが、カテゴリがロードされたタイミングで実行時に行われるという点で、これにより外部モジュールで基盤モジュールを置き換える事ができる。従ってカテゴリを用いればオリジナルコードの再コンパイルなしにルートクラスの挙動を変更する事さえ可能となる。また機能追加のためだけのサブクラス化を行なう必要がなくなる点は特筆に値する。
カテゴリが上述のInformalプロトコルに利用できるのは、ロードが実行時に行われるという構造上、コードのリンク時に実装が存在する保証がなく、インターフェースのみが先行する形になることから。
応用範囲は非常に広く、単純にクラス定義を複数の機能クラスターから構成するために用いる事もあれば、先に挙げたフレームワークのパッチやInformalプロトコルに用いるケースなど多岐にわたる。プログラムの可読性や設計のしやすさ全般に貢献しており、Objective-Cプログラマの間では「Javaの最大の弱点はカテゴリがないこと」などとささやかれるほどである。
[編集] カテゴリによるオーバーライドの例
@interface NSObject (BetterHash) - (unsigned)hash; @end @implementation NSObject (BetterHash) // 子孫クラスのうち、独自のオーバーライドのない-hashは全てこの実装に置き換わる - (unsigned)hash { return better_hash_function(self); } @end
[編集] その他
[編集] メタ言語的メカニズム
オブジェクトシステム自体がCで書かれていることに加え、C哲学である「プログラマにできることを制限しない」を良くも悪くも受け継いでいるため、Objective-Cにはさまざまな超言語的技法が存在している。これらの機能は非常に強力であるため乱用を避けるべきだが、この柔軟性こそがObjective-Cの魅力と評する向きもある。
- posing
- クラステーブルを書き換えることでクラスの実体を置き換える技法。
- method swizzling
- クラスのメソッドテーブルを書き換えることでセレクタ名のリネーミングを行なう技法。
- IMP呼びだし
- 毎回メッセージパッシングを行なう代わりに、一度だけメソッドを解決して関数ポインタを取り出し、メソッドの呼び出しを高速化する技法。呼びだしコストが通常のC関数と等しくなる。俗にインライン化とも呼ばれる。
[編集] Objective-C++
Objective-CとC++が混在したもの。両者はCからの拡張部分がほぼ干渉しないため、お互いをただのポインタ値と見なす事で表記が混在できる。従ってクラスシステムの互換性はなく、単純なObjective-C & C++になる。
主な用途はC++のライブラリをObjective-Cからアクセスするためのラッパー記述で、実例としてAppleのWebKit(KHTMLベース)などがある。コンパイル速度が非常に遅くなる事もあって積極的に用いられる事は少ない。
[編集] 言語ブリッジ
上述のように、Objective-Cランタイムシステムの実体はC言語関数群そのものである。このライブラリの内部でリフレクションやメッセージ送信の機構が全て閉じているため、これらに対するラッパーを用意することで、外部言語からシステムの完全制御が可能になる。
現在言語ブリッジが確立している言語には、Haskell、Java、Perl、Python、Rubyなどがある。
[編集] 処理系の特性
- Apple/NeXT版
- GNU版
- Portable Objective-C版
[編集] メモリ管理
初期のObjective-CプログラムはC同様単純な割当と解放を行なっていたが、現在はライブラリレベルで参照カウントを行なうのが一般的。OPENSTEPライブラリはイベントサイクル単位でAutorelease poolと呼ばれる暗黙の参照元を持っており、オブジェクトをここに登録することで事実上の自動解放オブジェクトを実現している。
今後はガベージコレクションに徐々に移行すると見られている。ただし両方式は一長一短があるという見方が支配的で、今後も併用される可能性が高い。GNU版ランタイムは独自にBoehm GCを使ったGCモードをすでに実現している。Apple版はMac OS X 10.5でGCを導入する予定。
[編集] 歴史
Objective-Cは、1983年にBrad Coxによって開発され、そのコンパイラやライブラリを支援するためにStepstone社を創立した。Stepstone社は、Objective-Cに力を注いだが、それはマイナーな存在であった。Objective-Cが認知され始めるきっかけは、1985年、アップルコンピュータを去ったスティーブ・ジョブズが、m68k機であるNeXTコンピュータとNeXTSTEPオペレーティングシステムの開発を行うNeXT Computer社を創立したことに始まる。
そのマシンのユーザインタフェースは、Display PostScriptと Objective-Cで書かれたApplication Kitにより提供され、Objective-CはNeXTコンピュータの主力言語となった。その後の歴史は、主にNeXT社とともにあり、GCCをベースにしたObjective-Cサポートが行われ、プロトコルの導入など文法の拡張なども行われている。NeXT社による多くの成果は、GCCに還元されている。
1995年には、NeXT社がStepstone社からObjective-C言語と、その商標に関する全ての権利を買い取っている。1997年初頭、Apple社がNeXT社を買収し、NeXT社CEOのジョブズがApple社のCEOに復帰したのに伴い、その技術をベースにしたオペレーティングシステムMac OS X上における、主力開発言語の一つとなっている。
[編集] 参考文献
Objective-Cに関する最初の本であり、Objective-Cを利用したオブジェクト指向システム開発に関する本。
- Object Oriented Programming: An Evolutionary Approach; Brad J. Cox, Andrew J. Novobilski; Addison-Wesley Publishing Company, Reading, Massachusetts, 1991; ISBN 0-201-54834-8
(邦題:「オブジェクト指向のプログラミング」 ISBN 4-8101-8046-8)
この本はObjective-CのNeXTSTEPでの実装について記述している。 NeXTSTEPが明確なターゲットだが、Objective-Cを学習するためのよい入門書となる。
- NeXTSTEP Object Oriented Programming and the Objective C Language; Addison-Wesley Publishing Company, Reading, Massachusetts, 1993; ISBN 0-201-63251-9
(邦題:「OBJECT-ORIENTED PROGRAMMING AND THE OBJECTIVE-C LANGUAGE (日本語版)」 ISBN 4-7952-9636-7)
多くの実例とともに、Stepstone版とNeXT版のObjective-Cについて、両者の違いを含めて論じている。
- Objective-C: Object Oriented Programming Techniques; Lewis J. Pinson, Richard S. Wiener; Addison-Wesley Publishing Company, Reading, Massachusetts, 1991; ISBN 0-201-50828-1
(邦題:「OBJECTIVE-C オブジェクト指向のプログラミング」 ISBN 4-8101-8054-9)
Objective-C、C++、Smalltalk、Object Pascal、Javaを比較しながら、オブジェクト指向プログラミングの話題を紹介している。
- An Introduction to Object-Oriented Programming; Timothy Budd; Addison-Wesley Publishing Company, Reading, Massachusetts; ISBN 0-201-54709-0
(邦題:「オブジェクト指向プログラミング入門」 ISBN 4-8101-8048-4)
[編集] 外部リンク
Objective-C言語とはどういうものかを知ることができる文書。
- The Objective-C Programming Language (日本語訳); Apple Computer, Inc.