連載

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

Chapter 10 継承とポリモーフィズム

株式会社ピーデー 川俣 晶
2004/06/24


 本記事は、(株)技術評論社が発行する書籍『VB6プログラマーのための入門 Visual Basic .NET 独習講座』の一部分を許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。

中身のないメソッドに対し、継承により中身を入れる

 継承時にメソッドの動作を入れ替えるや、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キーワードを使わない方法に相当する機能は記述できない。仮に記述できても、中身のないメソッドを呼び出すことは無意味であるため、使い道はない。

Protectedアクセス

 メソッドなどでは、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は継承を多用する場合に便利な機能であり、知っておく価値がある。

継承を禁止するNotInheritableキーワード

 クラスを宣言する際に、必ず継承しなければならないことを示す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を継承しようとしているが、これはエラーになる。内部の実装にトリックを使ったりして、継承すると不都合が起きるようなクラスを作った場合にも、このキーワードを付けておけば、エラーが起きて気付くことができる。


 INDEX
  [連載] 改訂版 プロフェッショナルVB.NETプログラミング
  Chapter 10 継承とポリモーフィズム
    1.Inheritsステートメントによる継承機能/クラス内で継承元クラスのメソッドを呼ぶ
    2.Windows FormにおけるInheritsステートメントの効果/継承時にメソッドの動作を入れ替える/Overridesキーワードを使って継承時にメソッドの動作を入れ替える
  3.中身のないメソッドに対し、継承により中身を入れる/Protectedアクセス/継承を禁止するNotInheritableキーワード
    4.ポリモーフィズム(異なる機能と共通の呼び出し方法)
    5.ポリモーフィズム(ソース・コードの弱点を分析/ポリモーフィズムを用いた書き換え)
    6.クラス・ライブラリに見るポリモーフィズムの実例 - その1/その2
 
「改訂版 プロフェッショナル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メールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH