【コラム】

ダイナミックObjective-C

2 Objective-Cの動的型付け

    木下誠  [2005/08/17]

    CocoaとObjective-Cの動的な特徴を探っていく本連載だが、今回は動的な型付けについて説明しよう。

    オブジェクトの型

    Objective-Cは、オブジェクト指向を取り入れたCの上位言語である。しかし、そのアプローチの仕方は、C++と比べるとかなり異なっている。C++が構造体を拡張する形でクラスを採用したのに対して、Objective-Cでは、オブジェクトのためにSmalltalkに近い完全に別の文法を取り入れている。

    つまり、Cと Smalltalkという異なる2つのスタイルの文法が入り交じることになる。これはObjective-Cが分かりにくい、と批判される理由のひとつとなっている。だが、通常のCの考えかたとオブジェクト指向はもともと別物だから、文法が異なるのは仕方が無い、と考えてしまえば、この割り切り方はいっそすがすがしいともいえる。

    さて、そんなObjective-Cでは、オブジェクトを表す新しい型を導入している。id型である。すべてのオブジェクトはid型で表す。インスタンスオブジェクトや、後述するようにクラスもオブジェクトとして扱われ、id型で表すことができる。つまり、Objective-Cは原理的に、id型のオブジェクトを実行時に判定する、動的型付けの言語である。

    しかし、静的型付けのように、クラス名をオブジェクトの型として使うこともできる。この場合、クラス名の後ろにアスタリスクをつけたもの、つまりクラス名のポインタといった形式が使われる。これは厳密にCの文法との整合性を考えると少しおかしいが、実際、すべてのオブジェクトはヒープ上に確保されることになるので、それほど的外れな文法ではないだろう。

    // id型のオブジェクトのための変数
    id object;
    // NSStringクラスのインスタンスのための変数
    NSString* string;

    このクラス名を伴う記法により、オブジェクトのクラスがコード上で分かることになり、コードの読みやすさや、コード補完機能が適切に使えるなど、静的型付けの利点を使うことができる。だが、クラスを指定して変数を宣言したとしても、そこに確かにそのクラスのインスタンスが入るかどうか、Objective-Cは実は何の保証もしない。たとえば、次のようなコードもそのままコンパイルできてしまう。

    // NSString型の変数を宣言
    NSString* string;
    // NSStringのインスタンスを確保して代入
    string = [[NSString alloc] init];

    // NSArray型の変数を宣言
    NSArray* array;
    // NSStringのインスタンスを、意図的にNSArray*型の変数に代入
    array = [[NSString alloc] init];

    上のサンプルの前半は、NSStringという文字列を取り扱うクラスのための変数を宣言し、インスンタンスを代入している。これは何の問題もない。それに対して後半は、NSStringのインスタンスを、NSArrayという配列のためのクラスの変数にわざと代入してみた。だが、これもコンパイルが通ってしまう。initメソッドはid型を返すので、警告すら出ない。

    もっと露骨に、違うクラスの型を持つ変数に直接代入したとしても、警告は出るものの、コンパイルは通る。そのまま実行しても、そのクラスのメソッドを呼び出さない限り、問題はない。これは、結局のところ、すべてのオブジェクトはid型になるからである。型の変換なども行われない。

    // NSArray型の変数に、NSString型の変数を代入
    // 警告は出るが、コンパイルは通る
    array = string;

    これで、Objective-Cのオブジェクト型は、原理的に動的型であり、静的な型は目安にすぎないことが理解できただろう。言語として型の厳密性を保証することはなく、適切なオブジェクトが代入させるかどうかの判断は、プログラマやフレームワークにまかされることになる。実際にコードを書いてみると、このいわばルーズな文法が、非常に楽であることに気づく。

    しかし、次のような疑問も浮かぶだろう。そんないい加減なコンパイルで、本当に実行時大丈夫なのか、と。これに対しては、次のように答えることができる。正しいオブジェクトが渡るかどうかはプログラマが保証することであり、ある程度の経験を積めば、基本的には大丈夫だろう、と。

    だが、本当の答えはこうではない。実は、このObjective-Cの動的な型付けこそが、Cocoaフレームワークの真髄になるのである。Cocoaは、この特性をフレームワークの根底から利用しており、それによって類をみない簡潔さを実現している。つまり、厳密なコンパイルを行うよりも、動的な型付けをうまく利用したフレームワークを使った方が利点が大きい、といえるのである。このことは本連載で、徐々に、具体的に、解き明かされていくだろう。

    次回は、id型で渡ってきたオブジェクトの、クラスやメソッドを調査する方法を紹介しよう。

    新着記事

    特設サイトの情報

      求人情報

      人気記事

      一覧

      イチオシ記事

      新着記事

      特別企画

      転職ノウハウ

      あなたの仕事適性診断

      4つの診断で、自分の適性を見つめなおそう!

      Heroes File ~挑戦者たち~

      働くこと・挑戦し続けることへの思いを綴ったインタビュー

      はじめての転職診断

      あなたにピッタリのアドバイスを読むことができます。

      転職Q&A

      転職に必要な情報が収集できます

      スカウト転職する

      企業からアプローチのメッセージが届きます。

      マイナビニュースマガジン