|
|
連載
プロフェッショナルVB.NETプログラミング
―― VB 6プログラマーのためのVB.NET入門 ――
第10回 オブジェクト関連(後編)
(株)ピーデー
川俣 晶
2002/06/22
|
Inheritsキーワードによる継承機能
継承は、VB 6(Visual basic 6.0)にはなく、VB.NET(Visual Basic .NET)になって初めて導入された機能である。しかし、似た機能がVB 6になかったわけではない。インターフェイスの機能が、やや継承と似た雰囲気を持っている。しかし、継承の方が、インターフェイスよりも、はるかに多くの機能を持っていて、「強化されたインターフェイス」を想像するだけでは、十分に把握しきれないものになるだろう。一度、頭の中を真っ白にして、新しい機能を学ぶ気持ちで読むとよいかもしれない。なお、ここでは、継承の主要な機能を説明するが、それだけでは具体的に何に使うか分からないかもしれない。今回はVB 6とVB.NETの機能の相違について取り上げ、継承機能をどのように使っていくかは、この連載のあとの方であらためて詳しく解説したい。
さて、継承は、あるクラスの機能を、別のクラスで引き継ぐことである。最も簡単な機能の引き継ぎは、あるクラスに含まれるメソッドを、別のメソッドからでも利用可能にすることだろう。
まず、こんなクラスを作ってみた。何の変哲もない、1個のメソッドを持つクラスである。
1: Public Class Class1
2: Public Sub Test1()
3: Trace.WriteLine("Test1 called")
4: End Sub
5: End Class
|
|
1個のメソッドを持つ簡単なクラスを定義したVB.NETのサンプル・プログラム1 |
次に、このクラスを継承するクラスを記述してみた。以下がそのクラスである。
1: Public Class Class2
2: Inherits Class1
3: Public Sub Test2()
4: Trace.WriteLine("Test2 called")
5: End Sub
6: End Class
|
|
サンプル・プログラム1のクラスを継承するVB.NETのサンプル・プログラム2 |
このコードで注目する必要があるのは、2行目のInheritsキーワードである。このキーワードに続いて、継承するクラスの名前を記述してある。これにより、CLass2はClass1の機能を継承していることになる。実際に継承できていることを確認するために記述したのが以下のコードである。
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.Test1()
5: 'o1.Test2()
6: o2.Test1()
7: o2.Test2()
8: End Sub
|
|
継承されていることを確認するためのVB.NETのサンプル・プログラム3 |
これを実行すると以下のようになる。
1: Test1 called
2: Test1 called
3: Test2 called
|
|
サンプル・プログラム3の実行結果 |
コード6行目のo2.Test1()は、Class2のインスタンスであるo2を経由して、Class1のメソッドTest1を呼び出そうとしている。これは、Class2がClass1を継承していることにより正常に機能する。しかし5行目のo1.Test2()のように、Class1のインスタンスに対して、Class2のメソッド呼び出しはできない。なぜなら、Class1自身は、Class2を継承しているわけではない(Class1には、“Inherits Class2”という記述がない)ためである。
なお、Class2にInherits Class1と記述したら、Class1にInherits Class2と記述することはできない。継承は循環できないのである。
この機能を用いれば、既存のクラスを書き換えることなく、容易に機能を追加できるようになる。例えば、基本機能だけを含む再利用可能なクラスを作っておき、個別のアプリケーション・ソフトでは、継承機能を用いて個々のソフトで必要になる独自機能を付け加えるなどが可能になる。
クラス内で継承元クラスのメソッドを呼ぶ
あるクラス内のメソッドから、同じクラス内のメソッドを呼び出すとき、いちいちインスタンスを明示せずとも、メソッドの名前だけで呼び出すことができる。これと同じことは、継承したクラスから継承元のメソッドを呼び出すときにも適用される。これを確かめるためにサンプル・プログラムを記述してみた。まずは継承元のクラスから。
1: Public Class Class1
2: Public Sub Test1()
3: Trace.WriteLine("Test1 called")
4: End Sub
5: End Class
|
|
継承元となるクラスを定義したVB.NETのサンプル・プログラム4 |
このクラスを継承した別のクラスを作成してみた。以下がその内容である。
1: Public Class Class2
2: Inherits Class1
3: Public Sub Test2()
4: Trace.WriteLine("Test2 called")
5: End Sub
6:
7: Public Sub TestCaller()
8: Test1()
9: Test2()
10: End Sub
11: End Class
|
|
サンプル・プログラム4を継承するVB.NETのサンプル・プログラム5 |
10行目のTest2()が、4〜6行目のTest2メソッドを呼び出すことは明らかだろう。だが、9行目のTest1()も、同様にClass1のTest1メソッドを呼び出すことができる。実際に呼び出せていることを、以下のようなコードで確かめてみよう。
1: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
2: Dim o2 As New Class2()
3: o2.TestCaller()
4: End Sub
|
|
クラスClass1のメソッドTest1が呼び出されることを確認するVB.NETのサンプル・プログラム6 |
これを実行すると以下のようになる。
1: Test1 called
2: Test2 called
|
|
サンプル・プログラム6の実行結果 |
これはメソッドだけでなく、プロパティでも同様にインスタンスを明示せず扱うことができる。
なお、継承元のメソッドは、常に継承先から呼び出し可能というわけではない。この例では、メソッドの宣言に付いたPublicキーワードが、呼び出し可能であることを示している。しかし、ここにPublicではなく、Privateキーワードが付加されている場合は、呼び出すことができない。
Windows FormにおけるInhritsキーワードの効果
VB 6では、以下のようなコードを記述することができる。
1: Private Sub Form_Load()
2: Debug.Print Width
3: Debug.Print Height
4: End Sub
|
|
フォームの大きさを表示するVB 6のサンプル・プログラム7 |
これを実行すると以下のようになる。
ここで、WidthやHeightというキーワードは、フォームのプロパティである。これらは、フォームのインスタンスを明示することなく記述できる。例えば、Me.Widthのようにフォームを明示しなくても利用できる。
これと同じようなコードをVB.NETでも記述することができる。以下は実際に記述してみた例である。
1: Public Class Form1
2: Inherits System.Windows.Forms.Form
3:
4: #Region " Windows フォーム デザイナで生成されたコード "
5:
6: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
7: Trace.WriteLine(Width)
8: Trace.WriteLine(Height)
9: End Sub
10: End Class
|
|
フォームの大きさを表示するVB.NETのサンプル・プログラム8 |
これを実行すると以下のようになる。なお、フォームのサイズが違えば結果も違う数値になる。VB 6とは座標系の初期値が違うので、かなり違う値になっているが、機能的には等価である。
このコードの7行目のWidthは、2行目のInheritsで指定されたSystem.Windows.Forms.Formという名前のクラスが持つプロパティである。このクラスを継承しているクラスForm1の内部なので、これはインスタンスを明示することなく呼び出せるわけである。Heightも、Widthと同じ仕組みである。
一見すると、このコードはVB 6の場合とよく似ているが、VB.NETでは継承というメカニズムを通じてプロパティが利用可能になっているという点で、微妙に異なっている点に注意が必要である。この事例では、System.Windows.Forms.Formというクラスを継承しているから、インスタンスを明示しないWidthは、このクラスのプロパティを参照する。しかし、ほかのクラスを継承したクラス内では、同じWidthというキーワードがまったく別のクラスのメソッドを指し示すかもしれない。