继承的基础知识 (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 的基类版本的调用。

另请参阅