SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Cでわかるオブジェクト指向

【第2回】カプセル化


オブジェクト指向の基本 - カプセル化

カプセル化とは

 「カプセル化(encapsulation)」とは、オブジェクト指向の基本的な概念の1つです。カプセル化について、Wikipediaを参照すると、次のように説明されています。

 オブジェクト内部のデータを隠蔽したり(データ隠蔽)、オブジェクトの振る舞いを隠蔽したり、オブジェクトの実際の型を隠蔽したりすること。

 また、カプセル化を行う利点については、次のように説明されています。

 外部のプログラムがデータ内部に直接アクセスを行っていた場合、このデータにアクセスしていたすべての箇所を同時に変更しなければならない。しかし公開メソッドを用いていれば、変更は内部表現から外部表現への公開メソッド内のみで済み、変更の影響を局所にとどめる事ができる。

 グローバル変数の問題などに直面することの多い組込み系のプログラマであれば、上記のメリットを十分に理解してもらえるものと思います。そして、この概念を実現することが、十分なオブジェクト化を実現し、OOPの旨味を味わうための第1歩となります。

図1 カプセル化の概念
図1 カプセル化の概念

 それでは、前回のコードをベースに、カプセル化の概念をCで実現していきましょう。

Cによるカプセル化の実現

 まずはオブジェクトを利用する側のプログラムからオブジェクトの持つ属性を参照できないようにする必要があります。ObjectClassクラスの定義を次のように変更します。

< リスト2 > C言語によるカプセル化の実現のサンプル(ObjectClass.h)
#ifndef _OBJECTCLASS_H_INCLUDE_
#define _OBJECTCLASS_H_INCLUDE_

/* クラスの定義 */
typedef struct _object Instance;
struct _object{
  void* encapsulation_data; /* 属性領域をカプセル化 */
  int (*message)(Instance* self);
};

/* オブジェクト生成メソッド */
Instance* Object_new(char* name, int status);
/* オブジェクト破棄メソッド */
void Object_delete(Instance* obj);

#endif

 クラス定義に存在していた属性の定義を削除し、代わりに属性用の構造体を格納する領域としてencapsulation_dataを追加しました。また、encapsulation_dataに何が格納されるか(具体的な属性用の構造体)は明らかにしていません。これにより、オブジェクトを利用する側のプログラムから属性を参照することはできなくなりました。

 さて、次はオブジェクト内部から属性にアクセスできるようにしていきましょう。

 まずは、ObjectClass.cの先頭で属性用の構造体および属性にアクセスするためのマクロを定義します。

< リスト3 >  ObjectClass.cの変更(部分) その1
/* ObjectClass属性定義 */
struct _objectclass_attribute {
  char* name;
  int status;
};                   
/* ObjectClass属性アクセス用マクロ */
#define OBJECT_CLASS_ATTRIBUTE(ptr)((struct _objectclass_attribute*)(ptr->encapsulation_data))

 また、オブジェクト生成・破棄メソッドは、上記にて定義した属性構造体用のメモリ領域の確保・解放の処理を行うように変更します。

< リスト4 >  ObjectClass.cの変更(部分) その2
/* オブジェクト生成メソッド */
Instance* Object_new(char* name, int status)
{
  Instance* obj = (Instance*)malloc(sizeof(Instance));

  /* 属性構造体を生成し、属性を初期化 */
  obj->encapsulation_data = malloc(sizeof(struct _objectclass_attribute));
  OBJECT_CLASS_ATTRIBUTE(obj)->name = name;
  OBJECT_CLASS_ATTRIBUTE(obj)->status = status;

  obj->message = Object_method;

  return obj;
}

/* オブジェクト破棄メソッド */
void Object_delete(Instance* obj)
{
  free(OBJECT_CLASS_ATTRIBUTE(obj));  /* 属性構造体の解放 */ 
  free(obj);    /* オブジェクト自身の解放 */
}

 最後に、具体的なメソッドにおける属性へのアクセス方法を以下にように変更します。

< リスト5 >  ObjectClass.cの変更(部分) その3
/* メソッドの実装 */
static int Object_method(Instance* self)
{
  printf("%s.status = %d\n", 
         OBJECT_CLASS_ATTRIBUTE(self)->name, 
         OBJECT_CLASS_ATTRIBUTE(self)->status);
  return 1;
}

次のページ
まとめ

この記事は参考になりましたか?

Cでわかるオブジェクト指向連載記事一覧

もっと読む

この記事の著者

島田 浩二(Ruby札幌)(シマダ コウジ)

1978年生まれ。電気通信大学電気通信学部情報工学科卒業後、メーカ系ソフトウェア会社にて携帯電話の開発業務に従事した後、2006年より札幌にてフリーのプログラマとして活動。2009年7月に株式会社えにしテックを設立し、同社代表取締役に就任。 日本Rubyの会理事、一般社団法人LOCAL理事、Ruby札幌主宰。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/3707 2009/03/17 12:59

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー