はじめに
前回はLuxMenuの実装を行いましたが、今回からはそのLuxMenuの内容が果たしてどのようなコードで実現されているのかを解説していきます。
LuxMenuが提供するモジュールの解説から行いたいところですが、前回説明した通り、LuxMenuはCOMコンポーネントとして提供しています。VC++環境ではMFCやATLなどを利用することで、比較的簡単にCOMコンポーネントを開発できますが、LuxMenuはActiveBasic 5.0(以下、AB)で開発されています。そこで、まずはABでどのようなコードを書けばCOMコンポーネントを生成できるのか、そもそもCOMコンポーネントとしてモジュールを作成するためには、どのようなロジックが必要になるのかを説明します。
準備
ABは下記のサイトから開発環境をダウンロードできます。お持ちでない方はインストールしておきましょう。
そもそもCOMとは?
COM(Component Object Model)とはクラスモジュールをバイナリレベルで連結したいという発想のもとに生まれた技術です(もちろん、利用用途はそれだけに留まりません)。簡単に言うと、あるクラスモジュールを外部アプリケーションで利用する場合、外部からの呼び出しが必要なメソッドを、インターフェイスを経由して提供する機能のことです。もともとはMicrosoft社が提唱するソフトウェア間通信の仕様規格であり、既存のソフトウェア市場を見ても非常に多くの部品がCOMによって構成されています。
また、COMコンポーネントは独特な識別ID(CLSID)によって区別されます。CLSIDはGUIDで構成されており、世界で1つだけの値を持つことができます。
インターフェイス
COMについての解説を始めると、至るところで「インターフェイス」という言葉が出てきます。このインターフェイスとは、クラスが提供する機能をメソッドベースでまとめ、定義付けたもののことです。
なかなかイメージが沸かない方のために少し具体的に説明しましょう。インターフェイスは現実の世界でもさまざまな意味を持ちます。例えば、皆さんが今使っているパソコンには、さまざまな端子(インターフェイス)があると思います。LAN端子にモジュラージャックを差し込むことはできませんし、その逆も無理な話です。インターフェイスを通じて、さまざまな機器との接続が可能になり、それらの機能を活用することができますが、然るべき経路を使って、それらの機器を接続させなければならないことは当たり前の話です。
ここで、話をプログラミングの話題に戻しましょう。COMの世界でインターフェイスと言うと、COMコンポーネントとそれを利用するアプリケーション間の繋ぎ目のことを指します。もっと簡単に言うと、インターフェイスとは、仮想関数の塊のことなのです。
インターフェイスのサンプルコード
ということで早速、インターフェイスを活用したサンプルコードをABで動かしてみましょう。
#N88BASIC
'クラスを定義
Class CTest
Inherits ITest
Public
Sub CTest()
Print "CTestのインスタンスを生成"
End Sub
Sub ~CTest()
Print "CTestのインスタンスを破棄"
End Sub
Override Sub ShowMsg()
Print "ShowMsg
メソッドが呼ばれました"
End Sub
End Class
'インターフェイスを定義
Interface ITest
Sub ShowMsg()
End Interface
' インターフェイスの生成
Function CreateInstance() As *ITest
Dim pObj As *CTest
pObj=New CTest()
Return pObj As *ITest
End Function
'インターフェイスの破棄
Sub Release(lpTest As *ITest)
Delete lpTest
End Sub
'-----------------------------------------------------
' 一般的なオブジェクト操作
'-----------------------------------------------------
Dim pobj_Test As *CTest
pobj_Test=New CTest()
pobj_Test->ShowMsg()
Delete pobj_Test
Print
Print
'-----------------------------------------------------
' インターフェイスを経由したオブジェクトへのアクセス
'-----------------------------------------------------
Dim lpTest As *ITest
lpTest=CreateInstance()
lpTest->ShowMsg()
Release(lpTest)
先頭の#N88BASIC
というのは、AB特有のディレクティブであり、N88BASICと互換性のある命令語を独自のプロンプト上で動作させるための意味を持ちます。随所でPrint
命令を出せるのはある意味うれしい仕様なのかもしれません。
まず、CTest
クラスを宣言しています。コンストラクタとデストラクタがあって、プロンプトに文字列を出力するだけのShowMsg
というメソッドを持つ、単純なクラスです。注目したいところは、ITest
を継承しており、ShowMsg
を実装しているところでしょうか。このように、明示的にITest
との関連性をアピールしています。
次に、CTest
に対応するインターフェイス、ITest
を宣言してみましょう。ABではインターフェイスを定義するのに、Interface
ステートメントを利用します。ITest
インターフェイスが提供する機能として、ShowMsg
を定義しておきましょう。続けてインターフェイスを生成するための関数および破棄するための関数(それぞれCreateInstance
、Release
)を用意します。内部では、New
とDelete
を呼び出し、CTest
オブジェクトの生成と破棄を行っています。外部からダイレクトにNew
、Delete
をさせないのがインターフェイスの生成と破棄のコツです。
最後に、定義したクラスやインターフェイスを使って一般的なオブジェクト操作と、インターフェイスを経由したオブジェクトへのアクセスを行ってみましょう。どうですか?ITest
からはまったくといっていいほど、CTest
が見えなくなってはいないでしょうか。内部的にはCTest
のオブジェクトが生成されるものの、表面的には、CreateInstance
でインターフェイスを生成し、実装されているShowMsg
メソッドを呼び出し、Release
で解放を行っているという形になっていますね。