コンテンツへスキップ

今どき VisualBasic6

訳あって、今どきVisualBasic 6(VB6)の仕事をしてます。 今後はもうVB6のプログラムを組むことはないと思うけど、調べたことも多いのでムダにならないようにまとめておきます。 普段JavaとかC#とかを使って開発している人が、どうしてもVB6を使わなければならなくなったときに役に立つかな。 また、一部のテクニックはVisual Basic for Applications( VBA )にも適用できるはずです。

いっぺんに書くと大変なので、3回に分けて以下の内容を書く予定。

  • 1回目言語のテクニック等
    • シングルトンクラスの定義
    • ヘンテコスコープ
    • キャスト
    • インスタンスの同一性検査
    • しっかり評価
  • 2回目開発環境テクニック
  • 3回目VisualC++で作ったDLLとの連携

1回目 言語のテクニック等

VB6はオブジェクト指向開発には向かないけれど、VB6をあの手この手でオブジェクト指向っぽく使いました。 1回目はその辺をまとめてみます。

シングルトンクラスの定義

VB6でクラスを宣言し、GlobalMultiUseに設定すればシングルトンクラスが定義できると思ったら甘い。 GlobalMultiUseなクラスをつくっても、DLLを跨いだときにインスタンスが共有できない。返って標準モジュールだと共有される。 ただし、デバッグ実行すると共有される。(も~!意味不明!) そういうわけで、シングルトンインスタンスが必要な場合は、すべてのクラスインスタンスのメソッド実装を標準モジュールへのdelegateとして実装すれば実現できる。

たとえばアプリケーション内で連番を管理するシングルトンクラスは以下のように宣言できる。

Singleton.cls クラスモジュール(GlobalMultiUse)

Public Function GetNext() As Integer
GetNext = LocalSingleton.GetNext()
End Function

''
' これがシングルトンクラスのコンストラクタに相当
Private Sub Class_Initialize()
Call LocalSingleton.InitializeLocalSingleton
End Sub

LocalSingleton.bas 標準モジュール

Private mCounter As Integer

Public Function GetNext() As Integer
mCounter = mCounter + 1
GetNext = mCounter
End Function

''
' メンバ変数を初期化
Public Sub InitializeLocalSingleton()
mCounter = 0
End Sub

ヘンテコスコープ

標準モジュール(.bas)とクラスモジュール(.cls)の間にはおかしなスコープが適用される。 知っていればどうと言うことはないが、ハマリ所なので押さえておくとよい。

同一プロジェクト内メソッドの呼び出し

↓呼びだし側/呼び出され側→.cls (GlobalMultiUse).cls (MultiUse).bas
.cls (GlobalMultiUse)
.cls (MultiUse)×
.bas×

同一プロジェクト内Enumの参照

↓参照側/被参照側→.cls (GlobalMultiUse).cls (MultiUse).bas
.cls (GlobalMultiUse)
.cls (MultiUse)
.bas

プロジェクトを跨ぐメソッドの呼び出し

↓呼びだし側/呼び出され側→.cls (GlobalMultiUse).cls (MultiUse).bas
.cls (GlobalMultiUse)×
.cls (MultiUse)×
.bas×

プロジェクトを跨ぐEnumの参照

↓参照側/被参照側→.cls (GlobalMultiUse).cls (MultiUse).bas
.cls (GlobalMultiUse)×
.cls (MultiUse)×
.bas×

キャスト

Javaを使っていたら簡単にキャストがかけるが、VB6だとそうもいかない。

ConcreteType tConcreteInstance = (ConcreteType)tAbstractInstance;

VBで同じ事をやるには以下のように書けばいい。

Dim tConcreteInstance As ConcreteType
Set tConcreteInstance = tAbstractInstance

キャストしつつのメソッド呼び出しは

((ConcreteType)tAbstractInstance).ConcreteTypeMethod();
Dim tConcreteInstance As ConcreteType
Set tConcreteInstance = tAbstractInstance
Call tConcreteInstance.ConcreteTypeMethod

こんな感じになりVB6は煩雑。 そこで、キャストを行うためのユーティリティメソッドを用意することにした。

' キャスト用メソッド定義
Public Function AsConcreteType(tObject As Object) As ConcreteType
Set AsConcreteType = tObject
End Function
' 呼び出し
Call AsConcreteType(tAbstractInstance).ConcreteTypeMethod

ちょっとは楽になった。

プリミティブ型については以下ようなキャストメソッドが用意されている。

  • CInt Integer型へキャスト
  • CLng Long型へキャスト
  • CSng Single型へキャスト
  • ・・・

インスタンスの同一性検査

関数VarPtr、ObjPtr、StrPtrを使うと変数やオブジェクトや文字列のアドレスを取得できる。ドキュメントには記載されていないが、開発環境上では入力補完してくれる。 そして、ObjPtrで得られる数値はインスタンスの同一性検査に利用できる。

しっかり評価

関数And、Orは左辺の真偽に関係なく必ず右辺を評価する。関数IIfは条件式の真偽に関係なく必ず真のときの式と偽のときの式を評価する。評価の省略を期待したコードを書くと痛い目にあうので注意。


1回目はこんなところで。 このほかにもVBのテクニックを知ってる人は教えてプリーズ。次回は以下の開発環境テクニックを書くッスよ~

  • UnitTest
  • 夜間自動ビルド&自動テスト
  • Subversionと連携する
  • DLLのバージョンとregsvr32について
  • コメントからドキュメントを生成する
  • リファクタリング

© 2003 Kurusugawa Computer Inc.