Win32 App What Is a COM Interface - yoshimune/LearningDirectX11 GitHub Wiki
This page refers to 【What Is a COM Interface?】
もしC#にかJavaについて知っているなら、インターフェイスについて知っているはずです。インターフェイスはオブジェクトがサポートするメソッドセットを、実装を抜きにして定義します。インターフェイスはメソッドを呼び出すコードとメソッドを実装するコードの教会を明確に示します。コンピュータ・サイエンスのテーマでは、呼び出し側は実装から分離されています。
C++では、インターフェイスに近いものは純粋なvirtualクラス(純粋なvirtualメソッドのみを含むクラス)です。以下はインターフェイスの仮説的な例です。
// The following is not actual COM.
// Pseudo-C++:
interface IDrawable
{
void Draw();
};
この例のアイディアはいくつかの描画可能グラフィックスライブラリ内のオブジェクトセットです。IDrawable
インターフェイスはいくつかの描画可能オブジェクトがサポートしなくてはならないオペレーションを定義します。(規約では、インターフェイス名は"I"から始めます。)この例では、IDrawble
インターフェイスは単一のオペレーションDraw
を定義しています。
全てのインターフェイスは abstract ですよってプログラムはIDrawable
のインスタンスを作成できません。例えば、以下のコードはコンパイルエラーになります。
IDrawable draw;
draw.Draw();
代わりに、グラフィックライブラリはIDrawable
インターフェイスが実装されたオブジェクトを提供します。例えば、ライブラリはshapeオブジェクトとbitmapオブジェクトを描画のために提供します。C++では、共通のベースクラスを継承することにより実現します。
class Shape : public IDrawable
{
public:
virtual void Draw(); // Override Draw and provide implementation.
};
class BitMap : public IDrawable
{
public:
virtual void Draw(); // Override Draw and provide implementation.
};
Shape
とBitmap
クラスはdrawableオブジェクトの2つの明確な形式を定義します。各々のクラスはIDrawable
から継承されます。また、各自のDraw
メソッドの実装を提供します。当然、2つの実装はかなり違っているかもしれません。例えば、Shape:Draw
メソッドは線のラスタライズをし、一方でBitmap::Draw
はピクセル配列をblitするかもしれません。
プログラムはグラフィックスライブラリを使ってShape
とBitmap
オブジェクトを通して、Shape
やBitmap
のポインタを直接扱うのではなく、IDrawable
ポインタを操作します。
IDrawable *pDrawable = CreateTriangleShape();
if(pDrawable)
{
pDrawable->Draw();
}
ここでは、IDrawableポインタの配列をループする例を示します。配列内のオブジェクトがIDrawable
を継承する限り、配列にはシェイプ、ビットマップ、その他のグラフィックオブジェクトの異種が含まれている場合があります。
void DrawSomeShapes(IDrawable **drawableArray, size_t count)
{
for(size_t i = 0 ; i < count ; i++)
{
drawableArray[i]->Draw();
}
}
COMのキーポイントは、コードの呼び出し側からは派生クラスの型を決して見ないことです。別の言い方をすると、Shape
型やBitmap
型の変数を宣言しないということです。シェイプとビットマップに関する全てのオペレーションは、IDrawable
を使って作用させます。この方法では、COMはインターフェイスと実装の厳格な分離を維持します。呼び出し側のコードを変更することなく、Shape
とBitmap
の実装を変更する(たとえば、バグ修正や機能追加など)ことができます。
C++の実装では、インターフェイスはクラスか構造体を使って宣言します。
このトピックでのサンプルコードは、一般的な概念を伝えるためのもので、実際の慣習ではありません。新しいCOMインターフェイスを定義することは、このシリーズの責任範囲を超えています。しかし、ヘッダーファイルに直接インターフェイスを定義することはありません。代わりに、COMインターフェイスはInterface Definition Language(IDL)と呼ばれるものを使って定義されます。IDLファイルはIDLコンパイラで処理され、C++のヘッダファイルを生成します。
class IDrawable
{
public:
virtual void Draw() = 0;
}
COMを利用するとき、重要なのは「インターフェイスはオブジェクトではない」ということを覚えておくことです。インターフェイスは、オブジェクトが実装しなくてはならないメソッドの集合です。いくつかのオブジェクトは、Shape
とBitmap
の例で見せたように、同じインターフェイスを実装できます。更に、一つのオブジェクトはいくつかのインターフェイスを実装することができます。例えば、グラフィックライブラリはグラフィックオブジェクトのセーブとロードを行うISerializable
インターフェイスを定義している場合があります。
次のクラス宣言を考えてみましょう。
// An interface for serialisation
class ISerializable
{
public:
virtual void Load(PCWSTR filename) = 0; // load from file.
virtual void Save(PCWSTR filename) = 0; // save to file.
};
// Declarations of drawable object types;
class Shape : public IDrawable
{
...
};
class Bitmap : public IDrawable, public ISerializable
{
...
};
この例では、Bitmap
クラスはISerializable
を実装しています。プログラムはこのメソッドを使ってビットマップをセーブ・ロードすることができます。しかし、Shape
クラスはISerializable
を実装していません。よって、機能を公開していません。