はじめに
VBAのクラスモジュールで、クラスの初期化処理などを作成する際、プロパティ名と、それに値を設定するためのメソッドの引数名が、同じになってしまうことがよくあります。
例えば、「商品」クラスが Name というプロパティを持ち、初期化メソッド Init の引数も Name だった場合、コード内で Name = Name と書いても、どちらがどちらを指しているのか分からなくなってしまいます。
このような名前の衝突(競合)を解決し、「これはクラス自身のプロパティです」と明示するために使うのが Me キーワードです。
この記事では、クラスモジュールにおける名前の競合問題と、Me キーワードを使ったスマートな解決方法について解説します。
名前の競合と Me を使った解決サンプルコード
この例では、Product というクラスを作成し、その初期化メソッド Initialize の中で、プロパティ ItemName と引数 ItemName の名前が競合する状況を解決します。
ステップ1: クラスモジュールを作成する
- VBEで「挿入」→「クラスモジュール」を選択します。
- プロパティウィンドウで、
(Name)をProductに変更します。 - 以下のコードを貼り付けます。
【クラスモジュール: Product】
' クラスのプロパティを定義
Public ItemName As String
Public UnitPrice As Long
' クラスを初期化するためのメソッド
Public Sub Initialize(ByVal ItemName As String, ByVal UnitPrice As Long)
' Meキーワードを使って、プロパティと引数を明確に区別する
' Me.ItemName は、このクラス自身の「ItemNameプロパティ」を指す
' 右辺の ItemName は、このSubプロシージャの「引数」を指す
Me.ItemName = ItemName
' こちらも同様
Me.UnitPrice = UnitPrice
End Sub
ステップ2: 動作確認用のマクロを作成(標準モジュール)
' Productクラスの動作を確認する
Sub TestProductClass()
' Productクラスの新しいインスタンスを作成
Dim myProduct As Product
Set myProduct = New Product
' Initializeメソッドを呼び出して、値を設定
myProduct.Initialize ItemName:="高機能マウス", UnitPrice:=5000
' 設定された値を表示して確認
MsgBox "商品名: " & myProduct.ItemName & vbCrLf & _
"単価: " & myProduct.UnitPrice & "円", vbInformation, "商品情報"
End Sub
コードの解説
Public Sub Initialize(ByVal ItemName As String, ...)
初期化メソッド Initialize の引数として、クラスのプロパティと同じ ItemName という名前の変数を定義しています。この Sub プロシージャの中では、単に ItemName と書くと、VBAは最もスコープが近い引数の方を指します。
Me.ItemName = ItemName
この一行が、名前の競合を解決する核心部分です。
Me: クラスモジュールのコード内では、Meはそのクラスのインスタンス自身を指す特別なキーワードです。Me.ItemName:Meを付けることで、「このクラスインスタンスが持つItemNameという名前のプロパティ」であることが明確になります。- 右辺の
ItemName:Meが付いていないため、これはローカルなスコープを持つ「引数のItemName」を指します。
結果として、この行は「このクラスの ItemName プロパティに、引数として受け取った ItemName の値を代入しなさい」という意味になり、意図通りにプロパティの値を設定することができます。
まとめ
今回は、クラスモジュール内でプロパティ名と引数名が競合した場合の解決策として、Me キーワードの使い方を解説しました。
- クラスモジュール内では、
Meはオブジェクト自身を指す。 Me.プロパティ名と記述することで、ローカル変数(引数など)と同じ名前であっても、クラスのプロパティであることを明示できる。
Me キーワードを適切に使うことで、引数名をプロパティ名と一致させることができ、コードの可読性が向上します。これは、オブジェクト指向プログラミングにおける基本的で重要なテクニックです。
