すべての変更を施した後のObjectClass.cの全体を以下に示します。
#include "ObjectClass.h"
#include <stdio.h>
#include <stdlib.h>
/* ObjectClass属性定義 */
struct _objectclass_attribute {
char* name;
int status;
};
/* ObjectClass属性アクセス用マクロ */
#define OBJECT_CLASS_ATTRIBUTE(ptr)((struct _objectclass_attribute*)(ptr->encapsulation_data))
/* メソッドの実装 */
static int Object_method(Instance* self)
{
printf("%s.status = %d\n",
OBJECT_CLASS_ATTRIBUTE(self)->name,
OBJECT_CLASS_ATTRIBUTE(self)->status);
return 1;
}
/* オブジェクト生成メソッド */
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); /* オブジェクト自身の解放 */
}
これで、カプセル化の実現は無事終了です。オブジェクトの外部から属性を隠ぺいしつつ、オブジェクト内部からは今までどおり属性にアクセスできるようになり、前回のコードの問題点を解決することができました。いかがでしょうか。
「処理とデータの関連を明示的に示してプログラムを安全に扱う」ことが、OOPの目的と聞くと、前回のようなプログラムでも問題がないように見えるかもしれません。しかし、「データにアクセスすることのできる処理を限定的にする」ことが出来ていなければ、それは十分な実現とは言えません。OOPにおいて重要なのは「データにアクセスすることのできる処理を限定的にする」ことであり、それを説明する概念が「カプセル化」です。
まとめ
今回はOOPの基本であるカプセル化という概念について、C言語を用いた実装例とともに解説しました。次回はいよいよ継承の解説に入って行こうと思います。
本稿が、少しでも皆さんのオブジェクト指向の理解に貢献できたのなら幸いです。次回もお楽しみに。
