繼承基本概念 (Visual Basic)

Inherits 陳述式可用來根據現有類別 (稱為「基底類別」) 宣告新類別 (稱為「衍生類別」)。 衍生類別會繼承 (並可擴充) 基底類別中定義的屬性、方法、事件、欄位和常數。 下一節描述一些繼承規則,以及可用來變更類別繼承或被繼承方式的修飾詞:

  • 根據預設,除非以 NotInheritable 關鍵字標記,否則所有類別都是可繼承的。 類別可以繼承自專案中的其他類別,也可以繼承自專案所參考其他組件中的類別。

  • 不同於允許多重繼承的語言,Visual Basic 在類別中只允許單一繼承;也就是說,衍生類別只能有一個基底類別。 雖然類別中不允許多重繼承,但類別可以實作多個介面,因此可以有效地達成相同結果。

  • 若要防止公開基底類別中受限制的項目,衍生類別的存取類型必須與其基底類別同樣嚴格或更嚴格。 例如,Public 類別無法繼承 FriendPrivate 類別,而 Friend 類別無法繼承 Private 類別。

繼承修飾詞

Visual Basic 引進下列類別層級陳述式和修飾詞,以支援繼承:

  • Inherits 陳述式 - 指定基底類別。

  • NotInheritable 修飾詞 - 防止程式設計人員使用該類別作為基底類別。

  • MustInherit 修飾詞 - 指定該類別只能作為基底類別。 無法直接建立 MustInherit 類別的執行個體;這些類別只能建立作為衍生類別的基底類別執行個體。 (C++ 和 C# 等其他程式設計語言會使用「抽象類別」一詞來描述此類別)。

覆寫衍生類別中的屬性和方法

衍生類別預設會從其基底類別繼承屬性和方法。 如果繼承的屬性或方法必須在衍生類別中有不同的行為,則可加以「覆寫」。 也就是說,您可以在衍生類別中定義方法的新實作。 下列修飾詞是用來控制如何覆寫屬性及方法:

  • Overridable - 允許在衍生類別中覆寫類別中的屬性或方法。

  • Overrides - 覆寫基底類別中定義的 Overridable 屬性或方法。

  • NotOverridable - 防止在繼承類別中覆寫屬性或方法。 根據預設,Public 方法是 NotOverridable

  • MustOverride - 需要衍生類別覆寫屬性或方法。 使用 MustOverride 關鍵字時,方法定義只會包含 SubFunctionProperty 陳述式。 不允許其他陳述式,特別是沒有 End SubEnd Function 陳述式。 MustOverride 方法必須在 MustInherit 類別中宣告。

假設您想要定義類別來處理薪資。 您可以定義泛型 Payroll 類別,其中包含計算典型一週薪資的 RunPayroll 方法。 然後,您可以使用 Payroll,作為分配員工紅利時可能使用之更特製化 BonusPayroll 類別的基底類別。

BonusPayroll 類別可以繼承和覆寫基底 Payroll 類別中定義的 PayEmployee 方法。

下列範例會定義基底類別 Payroll, 和衍生類別 BonusPayroll,以覆寫繼承的方法 PayEmployeeRunPayroll 程序會建立 Payroll 物件和 BonusPayroll 物件並接著傳遞給 Pay 函式,以執行這兩個物件的 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 不能在模組中使用。

  • MyBase 不能用來存取標記為 Friend 的基底類別成員 (如果該基底類別位於不同的組件中)。

如需詳細資訊和其他範例,請參閱操作說明:存取衍生類別所隱藏的變數

MyClass 關鍵字

MyClass 關鍵字的行為就像參考原本實作類別目前執行個體的物件變數一樣。 MyClass 類似於 Me,但 MyClass 上的每個方法和屬性呼叫都會當做方法或屬性是 NotOverridable 來處理。 因此,方法或屬性不會因在衍生類別中覆寫而受到影響。

  • MyClass 是關鍵字,而非實際物件。 MyClass 不能指派給變數、傳遞給程序,或用於 Is 比較。

  • MyClass 是指包含類別及其繼承的成員。

  • MyClass 可作為 Shared 成員的限定詞。

  • MyClass 不能在 Shared 方法內使用,但可在執行個體方法內用來存取類別的共用成員。

  • MyClass 不能在標準模組中使用。

  • MyClass 可用來限定基底類別中定義且沒有該類別中所提供方法實作的方法。 這類參考與 MyBase. 方法具有相同意義。

下列範例會比較 MeMyClass

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 覆寫 testMethoduseMyClass 中的 MyClass 關鍵字也會使覆寫無效,而且編譯器會解析 testMethod 的基底類別版本呼叫。

另請參閱