継承の基本 (Visual Basic)
Inherits ステートメントは、既存のクラス (基本クラス) に基づいて新しいクラス (派生クラス) を宣言するときに使用します。 派生クラスは、基本クラスで定義されているプロパティ、メソッド、イベント、フィールド、および定数を継承します。また、派生クラスでこれらのプロパティ、メソッド、イベント、フィールド、および定数を拡張することもできます。 ここでは、継承の規則の一部と、クラスの継承方法を変更するための修飾子について説明します。
既定では、NotInheritable キーワードが指定されていない限り、すべてのクラスを継承できます。 継承するクラスは、プロジェクト内の他のクラスでも、プロジェクトが参照している他のアセンブリのクラスでもかまいません。
多重継承をサポートしている言語もありますが、Visual Basic がサポートしているのは単一継承だけです。したがって、派生クラスの基本クラスは常に 1 つだけです。 クラスでは多重継承することはできませんが、複数のインターフェイスを実装することはできます。複数のインターフェイスを実装すると、多重継承と同様の結果が得られます。
基本クラスで制限されている項目が公開されるのを防ぐため、派生クラスのアクセス レベルは、基本クラスと同等またはそれより制限の厳しいレベルにする必要があります。 たとえば、Public クラスは Friend クラスまたは Private クラスを継承できません。また、Friend クラスは Private クラスを継承できません。
継承の修飾子
Visual Basic では、継承をサポートするために、次に示すクラス レベルのステートメントと修飾子が導入されています。
Inherits ステートメント — 基本クラスを指定します。
NotInheritable 修飾子 — クラスを基本クラスとして使用できないように指定します。
MustInherit 修飾子 — クラスを基本クラスとしてだけ使用するように指定します。 MustInherit クラスのインスタンスは直接作成できません。派生クラスの基本クラス インスタンスとして作成する必要があります。 このようなクラスは、C++ や C# などの他のプログラミング言語での抽象クラスに相当します。
派生クラスにおけるプロパティとメソッドのオーバーライド
既定では、派生クラスは基本クラスのプロパティとメソッドを継承します。 継承されたプロパティまたはメソッドが派生クラスの中で異なる動作をしなければならない場合、このプロパティまたはメソッドをオーバーライドできます。 つまり、派生クラスに、メソッドの新しい実装を定義できます。 プロパティやメソッドのオーバーライド方法を制御するには、次の修飾子を使用します。
Overridable — 派生クラスにおけるプロパティやメソッドのオーバーライドを許可します。
Overrides — 基本クラスで定義されている Overridable のプロパティやメソッドをオーバーライドします。
NotOverridable — 継承するクラスでプロパティやメソッドのオーバーライドを禁止します。 既定では、Public メソッドは NotOverridable です。
MustOverride — 派生クラスにおけるプロパティやメソッドのオーバーライドを必須にします。 MustOverride キーワードを使用する場合、メソッドの定義で使用できるステートメントは、Sub、Function、および Property の各ステートメントだけです。 その他のステートメントは使用できません。特に、End Sub ステートメントや End Function ステートメントも使用しません。 MustOverride メソッドは、MustInherit クラスで宣言する必要があります。
給与支払いを処理するクラスを定義するとします。 まず、通常の 1 週間分の給与を計算する RunPayroll メソッドを含む汎用の Payroll クラスを定義します。 次に、Payroll を基本クラスとして、より特化した BonusPayroll クラスを作成します。これはボーナスの支給時に使用します。
BonusPayroll クラスでは、基本の Payroll クラスで定義されている PayEmployee メソッドを継承し、オーバーライドできます。
次の例では、基本クラス Payroll, と派生クラス BonusPayroll を定義しています。この派生クラスは、継承したメソッド PayEmployee をオーバーライドします。 RunPayroll プロシージャは、Payroll オブジェクトと BonusPayroll オブジェクトを作成し、Pay 関数に渡します。この関数は、この 2 つのオブジェクトの PayEmployee メソッドを実行します。
Const BonusRate As Decimal = 1.45D
Const PayRate As Decimal = 14.75D
Class Payroll
Overridable Function PayEmployee(
ByVal HoursWorked As Decimal,
ByVal PayRate As Decimal) As Decimal
PayEmployee = HoursWorked * PayRate
End Function
End Class
Class BonusPayroll
Inherits Payroll
Overrides Function PayEmployee(
ByVal HoursWorked As Decimal,
ByVal PayRate As Decimal) As Decimal
' The following code calls the original method in the base
' class, and then modifies the returned value.
PayEmployee = MyBase.PayEmployee(HoursWorked, PayRate) * BonusRate
End Function
End Class
Sub RunPayroll()
Dim PayrollItem As Payroll = New Payroll
Dim BonusPayrollItem As New BonusPayroll
Dim HoursWorked As Decimal = 40
MsgBox("Normal pay is: " &
PayrollItem.PayEmployee(HoursWorked, PayRate))
MsgBox("Pay with bonus is: " &
BonusPayrollItem.PayEmployee(HoursWorked, PayRate))
End Sub
MyBase キーワード
MyBase キーワードは、クラスの現在のインスタンスの基本クラスを参照するオブジェクト変数のように動作します。 MyBase は、派生クラスでオーバーライドまたはシャドウされている基本クラスのメンバーにアクセスする目的でよく使用されます。 特に、派生クラスのコンストラクターから基本クラスのコンストラクターを明示的に呼び出すために、MyBase.New がよく使用されます。
たとえば、基本クラスから継承したメソッドをオーバーライドする派生クラスをデザインするとします。 この場合は、次の例で示すように、オーバーライドしたメソッドで基本クラスのメソッドを呼び出し、戻り値を変更できます。
Class DerivedClass
Inherits BaseClass
Public Overrides Function CalculateShipping(
ByVal Dist As Double,
ByVal Rate As Double) As Double
' Call the method in the base class and modify the return value.
Return MyBase.CalculateShipping(Dist, Rate) * 2
End Function
End Class
MyBase を使用するときには、次の制約があります。
MyBase が参照するのは、直接の基本クラスとそこで継承されているメンバーです。 クラスの Private メンバーへのアクセスには使用できません。
MyBase はキーワードであり、実際のオブジェクトではありません。 MyBase は変数に代入したり、プロシージャに渡したりできません。また、Is 比較で使用することもできません。
MyBase で修飾するメソッドは、必ずしも直接の基本クラスで定義される必要はありません。間接的に継承されている基本クラスで定義することもできます。 MyBase で修飾した参照が正しくコンパイルされるためには、呼び出しで使用されているパラメーターの名前と型に対応するメソッドが、いずれかの基本クラスに含まれている必要があります。
MyBase を使って基本クラスの MustOverride メソッドを呼び出すことはできません。
MyBase をそれ自体で修飾することはできません。 したがって、次のコードは無効です。
MyBase.MyBase.BtnOK_Click()
MyBase をモジュールで使用することはできません。
基本クラスが異なるアセンブリ内にある場合は、Friend と指定されている基本クラスのメンバーに MyBase を使ってアクセスすることはできません。
詳細および他の例については、「方法: 派生クラスによって非表示になっている変数にアクセスする (Visual Basic)」を参照してください。
MyClass キーワード
MyClass キーワードは、クラスの現在のインスタンスを元の実装に従って参照するオブジェクト変数のように動作します。 MyClass は Me と似ていますが、MyClass から呼び出されるメソッドおよびプロパティは、NotOverridable (Visual Basic) であるかのように扱われます。 したがって、メソッドまたはプロパティは、派生クラスでのオーバーライドによる影響を受けません。
MyClass はキーワードであり、実際のオブジェクトではありません。 MyClass は変数に代入したり、プロシージャに渡したりできません。また、Is 比較で使用することもできません。
MyClass が参照するのは、外側のクラスとそこで継承されているメンバーです。
MyClass は、Shared メンバーの修飾子として使用できます。
MyClass は、Shared メソッドの内部では使用できませんが、クラスの共有メンバーにアクセスするためにインスタンス メソッドの中で使用できます。
MyClass を標準モジュールで使用することはできません。
基本クラスで定義されていて、クラスで実装が提供されていないメソッドを、MyClass で修飾することもできます。 このような参照は、MyBase.Method と同じ意味になります。
Me と MyClass を比較した例を次に示します。
Class baseClass
Public Overridable Sub testMethod()
MsgBox("Base class string")
End Sub
Public Sub useMe()
' The following call uses the calling class's method, even if
' that method is an override.
Me.testMethod()
End Sub
Public Sub useMyClass()
' The following call uses this instance's method and not any
' override.
MyClass.testMethod()
End Sub
End Class
Class derivedClass : Inherits baseClass
Public Overrides Sub testMethod()
MsgBox("Derived class string")
End Sub
End Class
Class testClasses
Sub startHere()
Dim testObj As derivedClass = New derivedClass()
' The following call displays "Derived class string".
testObj.useMe()
' The following call displays "Base class string".
testObj.useMyClass()
End Sub
End Class
derivedClass は testMethod をオーバーライドしていますが、useMyClass の MyClass キーワードによってオーバーライドの影響は無効になり、testMethod の基本クラス バージョンに対する呼び出しが行われます。