連載
プロフェッショナルVB.NETプログラミング
第10回 オブジェクト関連(後編)
(株)ピーデー
川俣 晶
2002/06/22
|
|
インスタンスを作成せずに呼び出せるメソッド
VB 6には、厳密にピッタリ対応する機能が見あたらないのだが、VB.NETには、インスタンスを作成せずに呼び出せるメソッドを記述できる。以下はそれを記述したサンプル・プログラムである。
1: Public Class Class1
2: Public Shared Sub TestShare()
3: Trace.WriteLine("TestShare called")
4: End Sub
5:
6: Public Sub TestNonShare()
7: Trace.WriteLine("TestNonShare called")
8: End Sub
9: End Class
|
|
Sharedキーワードを使用してメソッドを定義したVB.NETのサンプル・プログラム9 |
このコードの2行目を見ていただきたい。Subキーワードの手前に、Sharedというキーワードが見えると思うが、これがインスタンスを作成せずに呼び出せるメソッドであることを示している。対比のために、6〜8行目に、通常のメソッドも記述してみた。
このクラスを利用するサンプル・プログラムを以下のように記述してみた。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Class1.TestShare()
3: Dim instance As New Class1()
4: instance.TestNonShare()
5: instance.TestShare()
6: End Sub
|
|
サンプル・プログラム9を利用するVB.NETのサンプル・プログラム10 |
これを実行すると以下のようになる。
1: TestShare called
2: TestNonShare called
3: TestShare called
|
|
サンプル・プログラム10の実行結果 |
見てのとおり、3行目のDim文でインスタンスを作成する前に、2行目でClass1のTestShareメソッドが呼び出されている。Class1.TestShare()という記述で分かるとおり、このような場合には、インスタンスではなく、クラス名を明示する。
しかし5行目のように、インスタンスの名前を明示して、それを経由してSharedキーワード付きのメソッドを呼び出すこともできる。
継承時にメソッドの動作を入れ替える
メソッドAを含むクラスAを継承して、クラスBを作るときに、メソッドAの内容を入れ替えたい場合がある。つまり、継承を単なる機能追加だけでなく、機能変更にも使用したいということである。
まず、以下のようなクラスがあったとしよう。
1: Public Class Class1
2: Public Sub Test()
3: Trace.WriteLine("Test in Class1 called")
4: End Sub
5: End Class
|
|
クラスを定義しているVB.NETのサンプル・プログラム11 |
次にこのクラスを継承したときに、Testメソッドに異なる動作をさせたいとしよう。実際に、それを記述したのが以下のサンプル・プログラムである。
1: Public Class Class2
2: Inherits Class1
3: Public Shadows Sub Test()
4: Trace.WriteLine("Test in Class2 called")
5: End Sub
6: End Class
|
|
Shadowsキーワードを使用してメソッドを置き換えるVB.NETのサンプル・プログラム12 |
このコードで注目すべき点は2つある。1つは、Class1とまったく同じ名前、同じ引数(つまり引数がないことが共通)というメソッドが、Class2にも存在すること。そして、もう1つは、3行目のSubキーワードの前にShadowsキーワードが記述されていることである。このShadowsキーワードが、継承元クラスにあるメソッドを隠し、このメソッドを有効にする。
これを呼び出すサンプル・プログラムを以下のように書いてみた。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim o1 As New Class1()
3: Dim o2 As New Class2()
4: o1.Test()
5: o2.Test()
6: Dim o3 As Class1
7: o3 = o2
8: o3.Test()
9: End Sub
|
|
サンプル・プログラム12を使用するVB.NETのサンプル・プログラム13 |
これを実行すると以下のようになる。
1: Test in Class1 called
2: Test in Class2 called
3: Test in Class1 called
|
|
サンプル・プログラム13の実行結果 |
4行目のo1.Test()のように、Class1のインスタンスから呼び出せば、もちろん、Class1のメソッドが実行される。しかし、5行目のo2.Test()のようにClass2のインスタンスから呼び出せば、Class2のメソッドが実行される。
しかし、7行目のように、Class2のインスタンスなのにClass1の変数に代入してからアクセスすると、Class1のメソッドが実行されてしまう。これは、変数の型(ここではClass1)が、呼び出すメソッドを決定しているためである。変数の型に関係なく、置き換えたメソッドを呼び出す場合は、次のOverridableキーワードを使う。
Overriesキーワードを使って継承時にメソッドの動作を入れ替える
継承時にメソッドの動作を入れ替えるには、もう1つの方法がある。Overriesキーワードを使用する方法である。
まず継承元クラスを以下のように変更する。
1: Public Class Class1
2: Public Overridable Sub Test()
3: Trace.WriteLine("Test in Class1 called")
4: End Sub
5: End Class
|
|
Overridableキーワードを使用してメソッドを定義したVB.NETのサンプル・プログラム14 |
2行目のSubキーワードの前に、Overridableキーワードを挿入する。次に、継承するクラスを以下のように修正する。
1: Public Class Class2
2: Inherits Class1
3: Public Overrides Sub Test()
4: Trace.WriteLine("Test in Class2 called")
5: End Sub
6: End Class
|
|
Ovverridesキーワードを使用してメソッドを置き換えるVB.NETのサンプル・プログラム15 |
3行目のSubキーワードの手前のキーワードを、Shadowsではなく、Overridesキーワードに入れ替える。これだけである。では、以下のコードで実際に動作を見るとどうなるだろうか。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim o1 As New Class1()
3: Dim o2 As New Class2()
4: o1.Test()
5: o2.Test()
6: Dim o3 As Class1
7: o3 = o2
8: o3.Test()
9: End Sub
|
|
サンプル・プログラム15を使用するVB.NETのサンプル・プログラム16 |
これを実行すると以下のようになる。
1: Test in Class1 called
2: Test in Class2 called
3: Test in Class2 called
|
|
サンプル・プログラム16の実行結果 |
見てのとおり、結果の3行目が、前のサンプル・プログラムと異なっていることが分かると思う。ここでは、7行目の“o3 = o2”でClass1型の変数にClass2型のインスタンスへの参照を代入しているが、8行目のo3.Test()でメソッドを呼び出すとき、間違いなくClass2のメソッドを呼び出している。
Overriesキーワードを使う方が使いやすいが、反面、性能的にはOverriesキーワードを使わない方法が優れる。どちらを使うかは、ケースバイケースで判断されるものだろう。また、Overriesキーワードを使う方法は、置き換える可能性のあるすべてメソッドに、あらかじめOverridableキーワードを付けておく必要がある。その点で、実際に継承される前から、継承を意識しておく必要があり、あまり手軽ではない。一方、Overriesキーワードを使わない方法は、継承する際にShadowsキーワードを付けるだけなので、継承を意識していないクラスを継承する場合にも容易に対応できる。