3-5. 抽象化

公開日: 21:57 3. オブジェクト指向編/3-5. 抽象化


データの抽象化とは、例えば詳細を渡すことなくプログラムに必要な情報を渡すといったように、重要な情報だけを外に出し詳細は隠すことを指します。

データの抽象化はプログラミング(と設計)のテクニックでありインタフェースと実装の切り分けに依存しています。 実生活のテレビを例にしてみると、電源のオンオフ、チャンネルの変更、音量の調整、そしてスピーカーやDVDプレイヤーなどの外部コンポーネントの追加などがありますが、内部の詳細はわからず、つまりテレビがどのようにして空気中やケーブルを通して信号を受信するか、どのように信号を変換するか、画面に表示するかはわかりません。

従って、テレビは内部の実装と外部インタフェースが明確に分離してると言え、内部の知識を必要とせずに電源ボタンやチャンネル切り替え、音量操作を行えます。

C++の用語で言えば、C++のクラスは素晴らしいレベルのデータ抽象化を備えています。クラスは外部に、オブジェクトの機能の利用や、内部実装の詳細を知らないステートなどのオブジェクトデータの操作のための充分な手段を供給します。

例えば、プログラム内では与えられた値の並び替えに関数がどのアルゴリズムを使うか知らなくてもsort()関数を呼び出すことが可能です。実際には、並び替え関数の実装の基礎はライブラリのリリースで変更され、インタフェースも変わらないうちは、関数呼び出しは動作します。

C++では、独自の抽象化データ型を定義するにはクラスを使います。データを標準出力に渡すには次のようにostreamクラスのcoutオブジェクトを使います。
#include <iostream>
using namespace std;

int main( )
{
   cout << "Hello C++" <<endl;
   return 0;
}

ここでは、どのようにcoutが画面にテキストを表示するか理解する必要はありません。インタフェースとcoutの実装が好きに変更できることだけを知っていれば良いです。



アクセスラベルによる抽象化

C++では、クラスへの抽象化インタフェースを定義するにはアクセスラベルを使います。クラスは0以上のラベルを含みます。

  • publicラベルで定義されたメンバはプログラムのあらゆる部分からアクセス可能です。ある形のデータ抽象化ビューはそのpublicメンバとして定義されます。
  • privateラベルで定義されたメンバはクラスを使うコードへアクセスできません。privateセクションはその型を使うコードから実装を隠します。
どのくらいの頻度でアクセスラベルを記述するか制限はありません。アクセスラベルは後続のメンバ定義のアクセスレベルを指定します。指定されたアクセスラベルは次のアクセスラベルかクラス本体の}が見つかるまで効果が残ります。

データ抽象化の利点

データ抽象化は2つの重要なアドバンテージを持ちます。

  • クラス内部はオブジェクトの状態を破壊し得る、不注意によるユーザレベルエラーから保護されます。
  • クラスの実装はユーザレベルコードの変更なしに要求やバグレポートに応じて段々と進化します。
クラスのprivateセクション内だけでデータメンバを定義することで、クラス作成者は自由にデータに変更を加える事ができます。実装を変更する場合、変更が影響するものを確認するためにクラスコードのみが調べられます。データがpublicであれば、古い記述のデータメンバへ直接アクセスする関数は破棄され ます。

データ抽象化の例

publicとprivateメンバで実装したクラスを持つあらゆるC++プログラムは、データ抽象化の例となります。次の例を考えてみましょう。
#include <iostream>
using namespace std;

class Adder{
   public:
      // コンストラクタ
      Adder(int i = 0)
      {
        total = i;
      }
      // 外部へのインタフェース
      void addNum(int number)
      {
          total += number;
      }
      // 外部へのインタフェース
      int getTotal()
      {
          return total;
      };
   private:
      // 外部から隠蔽されたデータ
      int total;
};
int main( )
{
   Adder a;
   
   a.addNum(10);
   a.addNum(20);
   a.addNum(30);

   cout << "合計 " << a.getTotal() <<endl;
   return 0;
}
上のコードをコンパイルし実行すると、次の結果が得られます。
合計 60

上述のクラスは数を足しあわせ、合計を返します。publicメンバaddNumとgetTotalは外部へのインタフェースであり、クラスを使うにはこれらを知っている必要があります。privateメンバtotalは使う側が知らなくてもいいものでありますが、クラスが正常に動作するために必要です。

戦略設計

抽象化はインタフェースと実装にコードを分離します。構成要素を設計している間、実装を変更してもインタフェースがそのまま残るよう、実装のインタフェースの独立を保つ必要があります。 その場合インタフェースを利用しているプログラムは影響されず、最新の実装で再コンパイルが必要になるだけになります。
  • ?±??G???g???[?d????u?b?N?}?[?N???A

0 件のコメント :

コメントを投稿