Objective-C
| Objective-C | |
|---|---|
| パラダイム | オブジェクト指向プログラミング |
| 設計者 | Brad Cox |
| 型付け | 弱い静的型付け |
| 主な処理系 | Apple版、GNU版 |
| 影響を受けた言語 | Smalltalk、C言語 |
| 影響を与えた言語 | Java |
| プラットフォーム | Mac OS X、GNUstep他 |
Objective-C(オブジェクティブ シー)はプログラミング言語の一種。C言語をベースにSmalltalk型のオブジェクト指向機能を持たせた上位互換言語。
Objective-CはNeXT、Mac OS XのOSに標準付属する公式開発言語である。OS Xのパッケージ版に開発環境がDVDで付属するほか、ユーザ登録をすれば無償でダウンロードできる(Xcodeの項目参照)。現在では主にアップルのMac OS XやiOS上で動作するアプリケーションの開発で利用される。
目次 |
[編集] 概要
Objective-CはCを拡張してオブジェクト指向を可能にしたというよりは、Cで書かれたオブジェクト指向システムを制御しやすいようにマクロ的な拡張を施した言語である。したがって、better Cに進んだC++とは異なり、C & Object Systemという考え方であり、ある意味2つの言語が混在した状態にある。
関数(メソッド)の定義と呼び出し方が独特であるため、Objective-Cのコードは一見C++以上にCとはかけ離れた独特の記述となる。しかし、言語仕様はCの完全上位互換であり、if/for/whileなどの制御文や、intなどのスカラー型、関数記法、宣言・代入といった基本的な文法はCに準拠する。一方オブジェクトシステムはSmalltalkの概念をほぼそのまま借用したもので、動的型のクラス型オブジェクト指向ランタイムを持ち、メッセージパッシングにより動作する。このことからしばしば「インラインでCの書けるSmalltalk」または「インラインでSmalltalkの書けるC」などと呼ばれる。Cとは異なるObjective-Cに特有の部分は、@で始まるコンパイラディレクティブで明示され、オブジェクトのメソッド呼び出しは[]で囲まれたメッセージ式で行われる。
最大の特徴はオブジェクトシステムが完全に動的という点で、実行時のクラス拡張、オブジェクト汎用型idの導入により型によらない動的配列・辞書など、インタプリタに近い記述力をもつことである。実際にコードそのものはネイティブコンパイルされるものの、動作原理はほぼインタプリタに近く、コンパイラ型言語としてはまれな柔軟性を発揮する。
したがって、C側から見れば一種のスクリプトインタプリタが乗っているような状態であり、逆にオブジェクトシステムからはOS機能や膨大なC言語資源を直接利用可能なインターフェースが備わっているといえる。また仮想マシンを持たずに済むため、取り回しも良い。パフォーマンスはJavaのような中間コード型言語よりも良好で、CやC++のようなネイティブコンパイル言語には劣るとされる。Objective-C特有のこの形態は双方のメリット・デメリットが明確で、実際的な使い勝手が非常に優れている。この特性に着目したのがNEXTSTEPで、UNIXとの互換性と先進的なオブジェクト指向環境の両立に成功し、その後のOS設計に大きな影響を与えることとなった。
後続言語への影響としては、特にJavaの基礎設計にその姿を見ることができる(SunがOPENSTEPに関わっていたことと関係がある)。
| クラス | 単一継承+インタフェース多重継承(プロトコル) 通常はルートクラスから継承 |
|---|---|
| オブジェクトシステム | 動的束縛、メタクラスを持つ |
| 型 | 動的型+見た目の静的型のハイブリッド |
| 実行速度 | コードはCと同等のネイティブコンパイル、メソッド呼び出しは動的ディスパッチを行なうのでやや遅延する。平均してC/C++より多少遅く、中間コード型言語(Javaなど)より数倍程度高速といわれる。ただし、クリティカルな部分はいつでもCに展開できるため、実行速度が問題になることはまずない。 |
| その他 | オブジェクトはポインタ互換、Cのスカラー型はオブジェクトではない |
[編集] 歴史
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社を買収し、2001年に登場したMac OS XのCocoaフレームワークのコア言語として採用されている。Mac OS X v10.5からは一部言語仕様の変更が行われObjective-C 2.0と呼ばれる(詳細は#Objective-C 2.0を参照)。
コンパイラおよび言語仕様は完全に公開されているものの、長らくNeXTおよびその後継であるMac OS XとiOSの専用言語に近い状態にある。2008年にiPhone OS(現iOS)のAPIが公開されて以降、習得者の人口が増える傾向にあるが、アップル社の開発環境は、徐々にLLVMベースへシフトしつつあり、GCC版は事実上のGNUstep専用と化しつつある。
[編集] 基本的な構文
[編集] メソッド呼びだし
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 = 1; obj = [[SomeClass alloc] init]; } return self; } // deallocは自身のリソースを解放してからスーパークラスに回す - (void)dealloc { [obj release]; [super dealloc]; } @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プロトコルに用いるケースなど多岐にわたる。プログラムの可読性や設計のしやすさ全般に貢献している。
[編集] カテゴリによるオーバーライドの例
@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同様単純な割当と解放を行なっていたが、現在は標準APIライブラリに実装された参照カウントを利用するのが標準的である。参照カウントによる自動ガベージコレクションとは異なり、参照カウンタの増加(retain)と減少・開放(release)は手動で扱う必要がある。[1] OPENSTEPライブラリはイベントサイクル単位で、Autorelease poolと呼ばれる暗黙の参照元を持っており、オブジェクトをここに登録することでイベント終了時には自動で解放されるオブジェクトを実現している。
今後はガベージコレクションに徐々に移行すると見られている。ただし両方式は一長一短があるという見方が支配的で、今後も併用される可能性が高い。GNU版ランタイムは独自にBoehm GCを使ったGCモードをすでに実現している。Apple版はMac OS X 10.5でGCを導入した。iPhoneのCocoa touchではリソース制限が厳しいことからGCは使われず、Autorelease方式を採用している。
[編集] Objective-C 2.0
AppleはMac OS X 10.5においてObjective-C 2.0という名称で言語仕様の変更を行った。
- ガベージコレクションの導入
- 世代別の保守的GCを導入し、GC管理下にあるオブジェクトは全てメモリ管理を自動化できる。なお、これに伴いCore FoundationのオブジェクトもGC管理下に置けるようになった。GCモードではマルチスレッド周りの性能が向上するとみられる。
- プロパティの導入
- C#などに採用されているプロパティが追加された。setter/getterの扱いが大幅に簡略化される。またKey-Value-Codingに関してドット記法が導入され、obj.propNameのようなアクセスができるようになった。メッセージ送信メタファからは逸脱した感もあるが、元々構造体が同じ記法を用いている上、メソッド呼び出しを正確に書くよりもはるかに記述量が減るため、実利主義のObjective-Cらしい拡張と言える。
- Fast Enumeration
- いわゆるforeach文の導入。
- プロトコルの強化
- 実装オプションのプロトコル定義が増えた。
- Class Extensions
- 実装をオプションにできない無名カテゴリ。実装必須のプライベートメソッドを(インターフェース的に)公開したくない時に用いる。Objective-Cでは動的ディスパッチを行うので、非公開メソッドでも呼び出しに制限がない点に注意。
- ランタイム構造の変更
- クラスのposingは廃止された。その代わりにメソッドの交換(セレクタのマッピングを入れ替える)が公式に用意され、カテゴリと組み合わせることでほぼ同じ機能を実現できる。その他にも、ランタイム周りはほとんど原形を留めないほどに手が入っている。
[編集] 脚注
- ^ macやIOsの標準APIでは基底クラスNSObjectに参照カウントを実装してあり、他のクラスがNSObjectを継承している。Apple IOs API Reference #NSObject (2012-01-20 閲覧)Apple mac API Reference #NSObject (2012-01-20 閲覧)メモリ管理プログラミングガイド(日本語)
[編集] 参考文献
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)
[編集] 外部リンク
- The Objective-C Programming Language (日本語訳)Apple Inc. - Objective-C言語とはどういうものかを知ることができる文書。
- マイコミジャーナル ダイナミックObjective-C
|
|||||||||||||||||