要するにインターフェイスの実装である。VB5.0を使用していた時代、Implements というモノがあることはうっすらと知っていたが、まったく使ったことが無かった。こちらでビットマップ保存処理を作ったとき、「似たような処理をメソッド分けするの面倒くさ。関数のポインタやInterfaceを使いたいねぇ」と嘆いていたら、ふと VB で Implements があったことが脳裏に浮かんだのさ。 で VB のヘルプを見たら、限りなく微妙なサンプルが載っていたが…、何だあれ?超手抜きじゃん(もし Microsoft Excel を持っているのならヘルプに載っているかもしれないので見てみると良いかも)。ということで自分なりに実験的に書いてみた。 VBでのインターフェイス実装は、ロケールを見て文言を日本語・英語に切り替えたり、ConvXxx(Src() As Byte, Ext() As Byte) のような文字列変換処理など、関数の型は共通だけど処理が異なるような場合に使えると思われるが、ここでは書庫ファイル関連処理をサンプルとした。動作させるには Unzip32.dll、Unlha32.dll、unrar.dll が必要なので、インターネットを彷徨って掻き集めてください。 以下はメインのロジック。Sub Main() のみの実行で、GUIは無い。 [mdlMain.bas] Option Explicit Sub main() 'RARクラスを宣言して、インターフェイス型を引数とする関数に渡す Dim ArchRar As New ClsArchiveRar Call PrintArch(ArchRar) Set ArchRar = Nothing 'LHAクラスを宣言して、実装メソッドを実行する Dim ArchLha As New ClsArchiveLha Debug.Print "[" & ArchLha.ClsArchive_ArchiveType & "]" Debug.Print "[" & ArchLha.ClsArchive_GetVersion & "]" Set ArchLha = Nothing 'インターフェイスクラスを宣言して、ZIPクラスを割り当てる Dim ArchZip As ClsArchive Set ArchZip = New ClsArchiveZip Debug.Print "[" & ArchZip.ArchiveType & "]" Debug.Print "[" & ArchZip.GetVersion & "]" Set ArchZip = Nothing End Sub '文字列表示 Private Sub PrintArch(ByRef TargetCls As ClsArchive) Debug.Print "[" & TargetCls.ArchiveType & "]" Debug.Print "[" & TargetCls.GetVersion & "]" End Sub
[実行結果] 以下はインターフェイスと各実装クラスである。インターフェイスでは変数と関数を定義することが出来る。実装クラスから両者(=インターフェイスの変数と関数のこと)へのアクセスは、「インターフェイスクラスのオブジェクト名 + "_" + 関数名 または 関数名」という命名規則に従った実装をすることで行う。 いまいち要領を得ないのであるが、変数へのアクセスは Get で値を取得することが出来るのみで、Set または Let により値を設定をすることが出来ないようだ。値の設定が駄目なのに、Property Let による値設定プロパティを記述しておかないと、実行時エラーとなる。まったくもって無駄というか、意味不明。 ちなみにVB5.0のヘルプには、Set(Let)することが出来ない旨の説明や関数の実装例は記述されておらず、極めて不親切であると言わざるを得ない。 [ファイル名:ClsArchive.cls オブジェクト名:ClsArchive] Option Explicit '書庫ファイルの種類を保持する変数 Public ArchiveType As String 'DLLバージョンを取得する関数 Public Function GetVersion() As Long '関数の型を定義するだけなので処理を書く必要は無い '何らかの処理を記述しても無視される End Function [ClsArchiveRar.cls] Option Explicit Implements ClsArchive Private Declare Function RARGetDllVersion Lib "unrar" () As Integer Public Property Let ClsArchive_ArchiveType(ByVal ArchiveType As String) '値の設定は出来ないの? End Property Public Property Get ClsArchive_ArchiveType() As String ClsArchive_ArchiveType = "RAR" End Property Public Function ClsArchive_GetVersion() As Long ClsArchive_GetVersion = RARGetDllVersion End Function [ClsArchiveLha.cls] Option Explicit Implements ClsArchive Private Declare Function UnlhaGetVersion Lib "UNLHA32" Alias "#2" () As Integer Public Property Let ClsArchive_ArchiveType(ByVal ArchiveType As String) '値の設定は出来ないの? End Property Public Property Get ClsArchive_ArchiveType() As String ClsArchive_ArchiveType = "LHA" End Property Public Function ClsArchive_GetVersion() As Long ClsArchive_GetVersion = UnlhaGetVersion End Function [ClsArchiveZip.cls] Option Explicit Implements ClsArchive Private Declare Function UnZipGetVersion Lib "unzip32" Alias "#94" () As Integer Public Property Let ClsArchive_ArchiveType(ByVal ArchiveType As String) '値の設定は出来ないの? End Property Public Property Get ClsArchive_ArchiveType() As String ClsArchive_ArchiveType = "ZIP" End Property Public Function ClsArchive_GetVersion() As Long ClsArchive_GetVersion = UnZipGetVersion End Function |