|
|
連載
改訂版
プロフェッショナルVB.NETプログラミング
Chapter 10 継承とポリモーフィズム
株式会社ピーデー
川俣 晶
2004/06/24 |
|
|
継承時にメソッドの動作を入れ替えるや、Overridesキーワードを使って継承時にメソッドの動作を入れ替えるで説明したとおり、継承を行う際にメソッドの中身を入れ替えることができる。それだけでなく、あらかじめ中身のないメソッドを用意しておき、継承時に中身を与えることもできる。これは、インターフェイスに似た使い方といえる。なお、ここでいう“中身がない”とは、実行すべきソース・コードが1行も存在しないメソッドのことではなく、宣言されているが実行できないメソッドを意味する。このような、少しややこしいものがVB.NETには存在しているわけである。
VB.NETで、中身のないメソッドを記述した例を次に示す(リスト10-21)。
1: Public MustInherit Class Class1
2: Public MustOverride Sub Test()
3: End Class
|
|
リスト10-21 MustOverrideキーワードとMustInheritキーワードを使用して、中身のないメソッドを記述したプログラム
|
ここで注目すべき点が2つある。1つは、2行目のMustOverrideキーワードである。これは、このメソッドは必ず継承したクラスでオーバーライドしなければならいことを示している。中身がない以上、当然の話ではあるが、継承により中身を与えずに使うことはできない。
もう1点は、1行目のMustInheritキーワードである。このキーワードは、そのクラスが継承しなければならないことを意味している。このクラスそのものはインスタンスを作成できず、常にこのクラスを継承したクラスを通して使われることになる。
では、これを継承して、中身を与えたクラスを記述してみよう(リスト10-22)。
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
|
|
リスト10-22 リスト10-21を継承して、メソッドの中身を記述したプログラム
|
さらににもう1つ。
1: Public Class Class3
2: Inherits Class1
3: Public Overrides Sub Test()
4: Trace.WriteLine("Test in Class3 called")
5: End Sub
6: End Class
|
|
リスト10-23 リスト10-21を継承した別のクラスを定義したプログラム
|
これらは、OverridesキーワードをSubキーワードの前に付ける必要があるだけで、特別な構文を使用する必要はない。
では、これらを呼び出すサンプルコードを記述してみよう(リスト10-24)。
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: Dim o3 As New Class3()
4: Dim o1 As Class1
5: o2.Test()
6: o3.Test()
7: o1 = o2
8: o1.Test()
9: o1 = o3
10: o1.Test()
11: End Sub
|
|
リスト10-24 リスト10-21と10-22を使用したプログラム
|
これを実行すると以下のようになる。
1: Test in Class2 called
2: Test in Class3 called
3: Test in Class2 called
4: Test in Class3 called
|
|
リスト10-25 リスト10-24の実行結果
|
ここで注目していただきたい部分は、コードの7〜10行目である。Class1型の変数に代入してからメソッドTestを呼び出しても、Class2やClass3で定義した内容が実行されている。つまり、MustOverrideキーワードには、Overridableと同様の機能が含まれているということである。それに対して、MustOverrideキーワードを使わない方法に相当する機能は記述できない。仮に記述できても、中身のないメソッドを呼び出すことは無意味であるため、使い道はない。
メソッドなどでは、PrivateやPublicといったキーワードを付けて、それにアクセスできる範囲をコントロールすることができる。意図しない行から呼び出されることのないように、このようなキーワードを正しく使うことは、ソフトウェアの品質を上げるためにも重要な意味がある。本書のサンプル・プログラムの中にも、分かりやすさのためにPublicとしているが、本当はPublicにすべきではないケースも含まれる。それはさておき、VB 6にはなかった新しいキーワードProtectedが、VB.NETには存在している。これは、継承を行った場合に意味がある機能を割り当てられたもので、継承がないVB 6に存在しないのは当然ともいえる。リスト10-26に、Protectedを使用したサンプル・プログラムを示す。
1: Public Class A
2: Protected Sub Sample1()
3: Trace.WriteLine("クラスAのSample1が呼ばれました")
4: End Sub
5: Public Sub Sample2()
6: Sample1()
7: End Sub
8: End Class
9:
10: Public Class B
11: Inherits A
12: Public Sub Sample3()
13: Sample1()
14: End Sub
15: End Class
16:
17: Public Class Form1
18: Inherits System.Windows.Forms.Form
19:
20: …Windows フォーム デザイナで生成されたコード…
21:
22: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
23: Dim instanceA As New A()
24: Dim instanceB As New B()
25: 'instanceA.Sample1()
26: instanceA.Sample2()
27: 'instanceB.Sample1()
28: instanceB.Sample2()
29: instanceB.Sample3()
30: End Sub
31: End Class
|
|
リスト10-26 Protectedキーワードを使用したプログラム
|
これを実行すると以下のようになる。
1: クラスAのSample1が呼ばれました
2: クラスAのSample1が呼ばれました
3: クラスAのSample1が呼ばれました
|
|
リスト10-27 リスト10-26の実行結果
|
Publicキーワードはどこからでも呼び出せることを指定し、Privateキーワードは同じクラス内からのみ呼び出せることを指定する。それに対して、Protectedキーワードは、同じクラスと、そのクラスを継承したクラスからのみ呼び出せることを指定する。そのため、6行目のように、同じクラスからの呼び出しは実現できる。また、13行目のように、クラスAを継承したクラスBからも呼び出すことができる。しかし、継承関係のないForm1クラス内からは呼び出せず、25行目や27行目の行からシングルクォートを取り除いて有効にするとビルド・エラーになる。Protectedは継承を多用する場合に便利な機能であり、知っておく価値がある。
クラスを宣言する際に、必ず継承しなければならないことを示すMustInheritキーワードについては、中身のないメソッドに対し、継承により中身を入れるで説明した。このほかに、継承を禁止するという逆の効能を持つキーワード、NotInheritableがある。リスト10-28は、それを使用した例である。
1: Public NotInheritable Class A
2: Private a As Integer
3: End Class
4:
5: Public Class B
6: Inherits A
7: Private b As Integer
8: End Class
|
|
リスト10-28 継承を禁止するNotInheritableキーワードを使用したプログラム(コンパイル・エラーとなる)
|
このように記述すると、ビルド時にエラーになる。ソースの1行目で、クラスAにはNotInheritableキーワードが付いているので、クラスAを継承することはできない。6行目で、クラスAを継承しようとしているが、これはエラーになる。内部の実装にトリックを使ったりして、継承すると不都合が起きるようなクラスを作った場合にも、このキーワードを付けておけば、エラーが起きて気付くことができる。
業務アプリInsider 記事ランキング
本日
月間