Grundlagen der Vererbung (Visual Basic)

Die Inherits-Anweisung wird verwendet, um eine neue Klasse zu deklarieren, die als abgeleitete Klasse bezeichnet wird, basierend auf einer vorhandenen Klasse, die als Basisklasse bezeichnet wird. Abgeleitete Klassen erben die in der Basisklasse definierten Eigenschaften, Methoden, Ereignisse, Felder und Konstanten und können diese erweitern. Im folgenden Abschnitt werden einige der Regeln für die Vererbung und die Modifizierer beschrieben, mit denen Sie die Art und Weise ändern können, wie Klassen erben oder geerbt werden:

  • Standardmäßig können alle Klassen geerbt werden, es sei denn, sie sind mit dem Schlüsselwort NotInheritable gekennzeichnet. Klassen können von anderen Klassen in Ihrem Projekt oder von Klassen in anderen Assemblys erben, auf die Ihr Projekt verweist.

  • Im Gegensatz zu Sprachen, die mehrfache Vererbung zulassen, lässt Visual Basic nur einzelne Vererbung in Klassen zu, d. h. abgeleitete Klassen können nur über eine Basisklasse verfügen. Obwohl die mehrfache Vererbung in Klassen nicht zulässig ist, können Klassen mehrere Schnittstellen implementieren, wodurch effektiv dieselben Ziele erreicht werden können.

  • Um das Verfügbarmachen eingeschränkter Elemente in einer Basisklasse zu verhindern, muss der Zugriffstyp einer abgeleiteten Klasse gleich seiner Basisklasse oder restriktiver sein. Beispielsweise kann eine Public-Klasse keine Friend- oder Private-Klasse erben, und eine Friend-Klasse kann keine Private-Klasse erben.

Vererbungsmodifizierer

Visual Basic führt die folgenden Anweisungen und Modifizierer auf Klassenebene ein, um Vererbung zu unterstützen:

  • Inherits-Anweisung: Gibt die Basisklasse an.

  • NotInheritable-Modifizierer: Verhindert, dass Programmierer die Klasse als Basisklasse verwenden.

  • MustInherit-Modifizierer: Gibt an, dass die Klasse nur als Basisklasse verwendet werden soll. Instanzen von MustInherit-Klassen können nicht direkt erstellt werden. Sie können nur als Basisklasseninstanzen einer abgeleiteten Klasse erstellt werden. (Andere Programmiersprachen, z. B. C++ und C#, verwenden den Begriff abstrakte Klasse, um eine solche Klasse zu beschreiben.)

Überschreiben von Eigenschaften und Methoden in abgeleiteten Klassen

Standardmäßig erbt eine abgeleitete Klasse Eigenschaften und Methoden von ihrer Basisklasse. Wenn sich eine geerbte Eigenschaft oder Methode in der abgeleiteten Klasse anders verhalten muss, kann sie überschrieben (außer Kraft gesetzt) werden. Das heißt, Sie können eine neue Implementierung der Methode in der abgeleiteten Klasse definieren. Mit folgenden Modifizierern steuern Sie das Überschreiben von Eigenschaften und Methoden:

  • Overridable: Ermöglicht das Überschreiben einer Eigenschaft oder Methode in einer Klasse in einer abgeleiteten Klasse.

  • Overrides: Überschreibt eine in der Basisklasse definierte Overridable Eigenschaft oder Methode.

  • NotOverridable: Verhindert, dass eine Eigenschaft oder Methode in einer erbenden Klasse überschrieben wird. Standardmäßig sind Public-Methoden NotOverridable.

  • MustOverride: Erfordert, dass eine abgeleitete Klasse die Eigenschaft oder Methode überschreibt. Wenn Schlüsselwort MustOverride verwendet wird, besteht die Methodendefinition nur aus der Sub-, Function oder Property-Anweisung. Es sind keine anderen Anweisungen zulässig, und insbesondere gibt es keine End Sub- oder End Function-Anweisung. MustOverride-Methoden müssen in MustInherit-Klassen deklariert werden.

Angenommen, Sie möchten Klassen definieren, um die Gehaltsabrechnung zu verarbeiten. Sie können eine generische Payroll-Klasse definieren, die eine RunPayroll-Methode enthält, die die Gehaltsabrechnung für eine typische Woche berechnet. Sie könnten dann Payroll als Basisklasse für eine spezialisiertere BonusPayroll-Klasse verwenden, die beim Verteilen von Mitarbeiterboni verwendet werden könnte.

Die BonusPayroll-Klasse kann die in der Basisklasse Payroll definierte PayEmployee-Methode erben und überschreiben.

Im folgenden Beispiel werden die Basisklasse Payroll, und eine abgeleitete BonusPayroll-Klasse definiert, die die geerbte Methode PayEmployee überschreibt. Eine RunPayroll-Prozedur erstellt ein Payroll-Objekt und ein BonusPayroll-Objekt, die sie dann eine Pay-Funktion übergibt, die die PayEmployee-Methode beider Objekte ausführt.

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

Das Schlüsselwort „MyBase“

Das Schlüsselwort MyBase verhält sich wie eine Objektvariable, die auf die Basisklasse der aktuellen Instanz einer Klasse verweist. MyBase wird häufig für den Zugriff auf Basisklassenmember verwendet, die in einer abgeleiteten Klasse überschrieben oder für die ein Shadowing durchgeführt wird. MyBase.New wird insbesondere verwendet, um explizit einen Basisklassenkonstruktor aus einem abgeleiteten Klassenkonstruktor aufzurufen.

Angenommen, Sie entwerfen beispielsweise eine abgeleitete Klasse, die eine Methode überschreibt, die von der Basisklasse geerbt wird. Die überschriebene Methode kann die Methode in der Basisklasse aufrufen und den Rückgabewert ändern, wie im folgenden Codefragment gezeigt:

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

In der folgenden Liste werden Einschränkungen für die Verwendung von MyBase beschrieben:

  • MyBase bezieht sich auf die unmittelbare Basisklasse und ihre geerbten Member. Es kann nicht verwendet werden, um auf Private Member in der Klasse zuzugreifen.

  • MyBase ist ein Schlüsselwort, kein echtes Objekt. MyBase kann nicht einer Variablen zugewiesen, an Prozeduren übergeben oder in einem Is-Vergleich verwendet werden.

  • Die Methode, die MyBase qualifiziert, muss nicht in der unmittelbaren Basisklasse definiert werden. Sie kann stattdessen in einer indirekt geerbten Basisklasse definiert werden. Damit ein mittels MyBase qualifizierter Verweis ordnungsgemäß kompiliert werden kann, muss eine Basisklasse eine Methode enthalten, die dem Namen und den Parametertypen entspricht, die im Aufruf vorkommen.

  • Sie können nicht MyBase verwenden, um MustOverride Basisklassenmethoden aufzurufen.

  • MyBase kann nicht verwendet werden, um sich selbst zu qualifizieren. Daher ist der folgende Code ungültig:

    MyBase.MyBase.BtnOK_Click()

  • MyBase kann nicht in Modulen verwendet werden.

  • MyBase kann nicht verwendet werden, um auf Basisklassenmember zuzugreifen, die als Friend gekennzeichnet sind, wenn sich die Basisklasse in einer anderen Assembly befindet.

Weitere Informationen und ein anderes Beispiel finden Sie unter Gewusst wie: Zugreifen auf eine Variable, die von einer abgeleiteten Klasse ausgeblendet wird.

Das Schlüsselwort „MyClass“

Das Schlüsselwort MyClass verhält sich wie eine Objektvariable, die auf die aktuelle Instanz einer Klasse verweist, wie sie ursprünglich implementiert wurde. MyClass ähnelt Me, aber jeder Methoden- und Eigenschaftsaufruf an MyClass wird so behandelt, als wäre die Methode oder Eigenschaft NotOverridable. Daher wird die Methode oder Eigenschaft nicht durch Überschreiben in einer abgeleiteten Klasse beeinflusst.

  • MyClass ist ein Schlüsselwort, kein echtes Objekt. MyClass kann nicht einer Variablen zugewiesen, an Prozeduren übergeben oder in einem Is-Vergleich verwendet werden.

  • MyClass bezieht sich auf die enthaltende Klasse und ihre geerbten Member.

  • MyClass kann als Qualifizierer für Shared Member verwendet werden.

  • MyClass kann nicht innerhalb einer Shared Methode verwendet werden, kann aber innerhalb einer Instanzmethode verwendet werden, um auf einen freigegebenen Member einer Klasse zuzugreifen.

  • MyClass kann nicht in Standardmodulen verwendet werden.

  • MyClass kann verwendet werden, um eine Methode zu qualifizieren, die in einer Basisklasse definiert ist und über keine Implementierung der in dieser Klasse bereitgestellten Methode verfügt. Ein solcher Verweis hat die gleiche Bedeutung wie MyBase.Method.

Im folgenden Beispiel wird Me mit MyClass verglichen.

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

Obwohl derivedClasstestMethod überschreibt, annulliert das Schlüsselwort MyClass in useMyClass die Auswirkungen des Überschreibens, und der Compiler löst den Aufruf zur Basisklassenversion von testMethod auf.

Siehe auch