連載

プロフェッショナルVB.NETプログラミング

第10回 オブジェクト関連(後編)

(株)ピーデー
川俣 晶
2002/06/22

Page1 Page2 Page3 Page4

インスタンスを作成せずに呼び出せるメソッド

 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キーワードを付けるだけなので、継承を意識していないクラスを継承する場合にも容易に対応できる。


 INDEX
  連載 プロフェッショナルVB.NETプログラミング
  第10回 オブジェクト関連(後編)
    1.Inheritsキーワードによる継承機能
  2.インスタンスを作成せずに呼び出せるメソッド
    3.中身のないメソッドに対し、継承により中身を入れる
    4.既定のプロパティ
 
「プロフェッショナルVB.NETプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間