連載
» 2007年03月22日 00時00分 公開

Symbian OS開発の勘所(3):C++によるオブジェクト指向開発のメリット (2/3)

[大久保 潤 管理工学研究所,@IT MONOist]

オブジェクト指向アプローチのメリット

 21世紀に入って随分たちますが、残念なことにオブジェクト指向を使った場合のメリットは、依然として常識レベルの知識になっていないようです。Cに固執する人の中には、「頑張ればCで書けないことはない」といい張る人が多いようです。しかし、書けるかどうかということと、楽に書けるか否かということはまったく別の話です。

 例えば以下に示すコードは、オブジェクト指向アプローチを取ったときに得られるメリットの典型例です(注)。


※注:
C++の構文をご存じない方のために記しておくと、newは後に続く型のオブジェクトを確保するC++の演算子です。ヒープ上への領域の確保と、型ごとの初期化関数の呼び出しを行います。


void Caller1()
{
    CReqA* req = new CReqA( 1 );  // 要求の作成
    Process(  req  );             // 要求を処理させる
    (以下略)
}
呼び出し側1

void Caller2()
{
    CReqB* req = new CReqB(1, 1);// 要求の作成
    Process(  req  );            // 要求を処理させる
    (以下略)
}
呼び出し側2

void    Process( CReqBase* req )
{
    req->Exec();                // 渡された要求の実行
}
呼ばれた側

 Caller1()、Caller2()ともに要求を作り、Process()という関数に引き渡しています。渡されたProcess()は、要求の実行を行います。「何が便利なのか」というクレームが出そうですが、よく見てください。Caller1()とCaller2()では確保している要求の型が違います。違うのに、Process()はその差を意識することなく実行を行っています。

 あまり便利そうに思えませんか? ではこんな例はどうでしょう。

  // どこかの関数の一部
  CReqBase    reqarray[100];
  (reqarrayに対する要求の格納処理)
  // 要求の一括実行
  for ( int i = 0;  ( i < 100 ); i++ )
    {
    if ( NULL != reqarray[ i ] )
      {
      reqarray[ i ]->Exec();  // 要求の実行
      }
    }
オブジェクト指向的なコード

 このとき、ポインタ配列reqarray[100]の内容が以下のようになっているとします。

 要求の一括実行を行うfor文は、個別の要求の型を意識することなく処理を行っています(正確にはCReqBase*を処理しているつもりしかありません)。従来のコードであれば、for文の中で個別の要求の型を読み分け、キャストか何かを行って実行していたのではないでしょうか。例えば以下のように。

  // どこかの関数の一部
  CReqBase    reqarray[100];
  (reqarrayに対する要求の格納処理)
  // 要求の一括実行
  for ( int i = 0;  ( i < 100 ); i++ )
    {
    if ( NULL != reqarray[ i ] )
      {
      if ( reqarray[ i ] がCReqAのオブジェクトなら )
        {
        (CReqA*)reqarray[ i ]->Exec();  // 要求の実行
        }
      else if ( reqarray[ i ] がCReqBのオブジェクトなら )
        {
    (以下略)
従来型のコードのイメージ

 この方式の素晴らしさは、reqarray[]がポイントするオブジェクトの種類が増えたときに発揮されます。従来型のコードのように、呼び出し側でオブジェクトの型を意識していると、要求の種類が増えたときに合わせて手直しをする必要があります。しかしオブジェクト指向的なコードの場合、呼び出し側のコードを一切触る必要がありません。どうでしょう、便利だと思いませんか。

 一般にオブジェクト指向をサポートしていると主張する場合、以下の3つの概念をサポートする必要があります。

カプセル化
関連するデータとメソッドを1つのオブジェクトに閉じ込めること。公開部と非公開部に分けて、不必要な情報をオブジェクト外部から隠すことができる(情報隠ぺい)。

継承
上位クラスの性質をすべて引き継いだうえで、さらに性質を加えた新しいクラスを作成すること。上位クラスとの差分を定義し、実装するだけで新しいクラスが作成できる。

ポリモーフィズム
同じメッセージに対して、受信側のオブジェクトがそれぞれ独自のやり方でメッセージを処理し、異なった振る舞いをすること。

 上記のコード例は、ポリモーフィズムのメリットを説明するものです。この考え方はSymbian OSの至るところで使われていて、文字列処理も非同期フレームワークもポリモーフィズムを利用して効率的な設計がされています。

 また、構造体のフィールドが勝手に触られてしまうというCの問題点は、オブジェクト指向ではカプセル化により解決されています。

Copyright © ITmedia, Inc. All Rights Reserved.