C++、VBや、VB.NET、C#にはクラスのインスタンスが自分自身とそのメンバを参照するためのキーワードがあります。 例えばC++ではthisポインタ、VBではMeキーワードなどです。 同様にC#ではthis及びbaseキーワード、VB.NETでは VBから引き続きMeが使われ、新たにMyClassとMyBaseというキーワードが採用されました。 VB.NETとC#でMyBase / baseというキーワードが採用された背景には、共通言語仕様ではクラスの多重継承が認められていないために基底クラスは常に一つであるため、C++のように任意の基底クラスを参照するためにキャストを行う必要がなくなったからと考えられます。
このようにVB.NETとC#の MyClass / this と MyBase / base はその機能や目的は同じであるといえます。 ですが、VB.NETにはMyClassに似た働きを持つMeキーワードが存在します。
Meと MyClassの機能の違いに言及する前に、Me・MyClass・MyBaseを使用した例によってその動作を見てみることにします。
Imports System ' 基底クラス Public Class BaseClass ' 基底クラスでのMethod() Protected Overridable Sub Method(ByVal keyword As String) Console.WriteLine("Method of BaseClass called by " + keyword) End Sub End Class ' 派生クラス Public Class DerivedClass Inherits BaseClass ' 派生クラスでのMethod() Protected Overrides Sub Method(ByVal keyword As String) Console.WriteLine("Method of DerivedClass called by " + keyword) End Sub ' 各キーワードでインスタンスのメソッドを呼び出すためのメソッド Public Sub CallMethods() ' MyBase による呼び出し MyBase.Method("MyBase") ' MyClass による呼び出し MyClass.Method("MyClass") ' Me による呼び出し Me.Method("Me") End Sub End Class ' アプリケーションのエントリーポイント Module MeMyclassMybase Sub Main() ' 派生クラスのインスタンスを作成 Dim inst As New DerivedClass() inst.CallMethods() End Sub End Module
Method of BaseClass called by MyBase Method of DerivedClass called by MyClass Method of DerivedClass called by Me Press any key to continue
この結果から分かるとおり、MyBaseはそのインスタンスの基底クラスのメンバを参照しているのに対し、MyClass及びMeはそのインスタンス自身のクラスのメンバを参照していることがわかります。 では、MyClassとMeは同じものといえるのでしょうか。 下位互換性のためにMeが残されたのでしょうか。 それともキーワードが二つあるからには何らかの違いがあるのでしょうか。
実際のところ、全く意味の同じキーワードが二種類存在するのは下位互換性のためだけではなく、ちゃんとした違いがあります。 ほとんどの機能はMeも MyClassも大差ないのですが、メソッドの呼び出しの時にはその違いがあらわれます。 その違いがあらわれるようなサンプルコードを次に示します。
Imports System ' 基底クラス Public Class BaseClass ' 基底クラスでのMethod() Protected Overridable Sub Method(ByVal keyword As String) Console.WriteLine("Method of BaseClass called by " + keyword) End Sub ' 各キーワードでインスタンスのメソッドを呼び出すためのメソッド Public Sub CallMethods() ' MyClass による呼び出し MyClass.Method("MyClass") ' Me による呼び出し Me.Method("Me") End Sub End Class ' 派生クラス Public Class DerivedClass Inherits BaseClass ' 派生クラスでのMethod() Protected Overrides Sub Method(ByVal keyword As String) Console.WriteLine("Method of DerivedClass called by " + keyword) End Sub End Class ' アプリケーションのエントリーポイント Module MeMyclassMybase Sub Main() ' 派生クラスのインスタンスを作成 Dim inst As New DerivedClass() inst.CallMethods() End Sub End Module
Method of BaseClass called by MyClass Method of DerivedClass called by Me Press any key to continue
今回は先ほどとは異なり、CallMethods()を基底クラスに配置しました。 そして、派生クラスDerivedClassのインスタンスを作成し、そのインスタンスからCallMethods()を呼び出しています。 結果を見てわかるとおり、MeとMyClassでは異なる文字列を出力していることがわかります。 つまり、Me.Method()はDerivedClass.Method()を呼び、MyClass.Method()は BaseClass.Method()を呼び出しています。
これは何を意味しているかというと、MyClassはインスタンスのクラスがどのクラスであるかに関わらず、確実にMyClassが用いられたクラスのメソッドを呼び出しているのに対し、Meの場合はMeが用いられたクラスが何であるかに関わらず、インスタンスのクラスのメソッド、つまり派生クラスでオーバーライドされたメソッドを呼び出していることになります。
さらに、派生クラスで基底クラスのメソッドをシャドウするとその挙動は変化します。 次のコードはそれを行ったものです(DerivedClass.Method()のOverridesキーワードをShadowsキーワードに変えています)。
Imports System ' 基底クラス Public Class BaseClass ' 基底クラスでのMethod() Protected Overridable Sub Method(ByVal keyword As String) Console.WriteLine("Method of BaseClass called by " + keyword) End Sub ' 各キーワードでインスタンスのメソッドを呼び出すためのメソッド Public Sub CallMethods() ' MyClass による呼び出し MyClass.Method("MyClass") ' Me による呼び出し Me.Method("Me") End Sub End Class ' 派生クラス Public Class DerivedClass Inherits BaseClass ' 派生クラスでのMethod() Protected Shadows Sub Method(ByVal keyword As String) Console.WriteLine("Method of DerivedClass called by " + keyword) End Sub End Class ' アプリケーションのエントリーポイント Module MeMyclassMybase Sub Main() ' 派生クラスのインスタンスを作成 Dim inst As New DerivedClass() inst.CallMethods() End Sub End Module
Method of BaseClass called by MyClass Method of BaseClass called by Me Press any key to continue
今度はMeもMyClassもBaseClass.Method()を呼び出しています。 このように、メソッドの呼び出しではMeとMyClassは多少挙動が異なるので注意が必要です。 通常の使用方法ならMyClassを用いた方がよけいなバグを生じる可能性は少ないと思います(しかし、VB時代からの習慣で、ついMeを使いたくなってしまいますが・・・)。