一般的なオブジェクト指向言語にはコンストラクタというオブジェクトを生成して初期化するための機構がありますが、VBAにはありません。ここではオブジェクトの初期化を簡単にする方法を解説します。
この記事の例では次のPersonクラスを使います。最初にクラスモジュールを追加して、Personというクラスを定義しておきます。
Private pName As String
Private pSex As String
Public Property Get Name() As String
Name = pName
End Property
Public Property Let Name(fullName As String)
pName = fullName
End Property
Public Property Get Sex() As String
Sex = pSex
End Property
Public Property Let Sex(mlelOrFemale As String)
pSex = mlelOrFemale
End Property
VBAにはコンストラクタがない
一般的なオブジェクト指向言語にはオブジェクトを生成して初期化するコンストラクタと呼ばれる特別な関数を定義することが出来ます。コンストラクタには引数を渡すことができ、オブジェクトを適切な値で初期化することが出来ます。
しかし、VBAにはコンストラクタやそれに類する機構がありません。そのためオブジェクトは生成した後、プロパティを適切な値で初期化する必要があります。
次のコードはPersonオブジェクトを生成して適切な値で初期化しています。
Sub sample()
Dim p1 As New Person
Dim p2 As New Person
p1.Name = "鈴木一郎"
p1.Sex = "男"
p2.Name = "山田花子"
p2.Sex = "女"
End Sub
Initializeイベントを契機にオブジェクトを初期化する
ユーザーが定義した独自クラスからオブジェクトを生成すると、Initializeイベントが発生します。クラスモジュールにClass_Initializeイベントプロシージャを追加して、オブジェクトが生成されたときにプロパティや変数の初期化処理を実行することが出来ます。
次のClass_InitializeイベントプロシージャをPersonクラスに追加してみましょう。
Private Sub Class_Initialize()
Me.Name = "名無しの権兵衛"
Me.Sex = "不明"
End Sub
次のコードを実行するとプロパティが初期化されていることがわかります。
Sub sample()
Dim p As New Person
MsgBox p.Name & vbLf & p.Sex
End Sub
この方法ではオブジェクトごとに異なる値で初期化することはできません。あくまでもデフォルト値を設定できるだけです。ただし、Singletonオブジェクト(プログラム中で1つだけしか生成されないオブジェクト)であればこの方法でうまく初期化できるかもしれません。
初期化メソッドを定義する
Class_Initializeイベントプロシージャはデフォルト値を設定することはできますが、オブジェクトごとに異なる値を設定することが出来ません。最初の例のように、オブジェクトのプロパティを1つ1つ設定することもできますが、まとめてプロパティを設定できる初期化用のメソッドを用意します。
名前は任意で構いませんが、ここではInitという名前にします。Personクラスに次のようにInitメソッドを追加します。
Public Sub Init(fullName As String, mlelOrFemale As String)
Me.Name = fullName
Me.Sex = mlelOrFemale
End Sub
次のコードを実行すると、オブジェクトが適切な値で初期化されていることがわかります。
Sub sample()
Dim p1 As New Person
Dim p2 As New Person
p1.Init "鈴木一郎", "男"
p2.Init "山田花子", "女"
MsgBox p1.Name & vbLf & p1.Sex
MsgBox p2.Name & vbLf & p2.Sex
End Sub
まとめ
ここでの例では、Class_InitializeイベントプロシージャやInitメソッドの恩恵は少ないかもしれませんが、もっと複雑なオブジェクトであれば、その便利さが実感できるでしょう。
Class_InitializeイベントプロシージャやInitメソッドを追加した最終的なPersonクラスは次のようになります。
Option Explicit
Private pName As String
Private pSex As String
Public Property Get Name() As String
Name = pName
End Property
Public Property Let Name(fullName As String)
pName = fullName
End Property
Public Property Get Sex() As String
Sex = pSex
End Property
Public Property Let Sex(mlelOrFemale As String)
pSex = mlelOrFemale
End Property
Private Sub Class_Initialize()
Me.Name = "名無しの権兵衛"
Me.Sex = "不明"
End Sub
Public Sub Init(fullName As String, mlelOrFemale As String)
Me.Name = fullName
Me.Sex = mlelOrFemale
End Sub