1、继承和多态是继承机制中十分重要的概念。继承是基于现有类创建一个新类的技术。其中,现有类称为基类或父类,创建的新类称为派生类或子类。派生类继承基类中所有的数据和操作,同时还可以添加需要的额外的数据和操作。通过继承,不仅可以重用基类的代码,还可以通过定义继承类的层次结构来反映业务实体之间的相互关系。在派生类中还可以重新定义基类中的成员,以及定义多个同名但功能不同的成员,这就是多态性。多态反映了继承的另外一个特性,即通过新类扩展现有类,在扩展时无需更改现有类的任何代码。利用多态性,可以根据未来的业务变化和需求,无缝扩展现有的类。本章将讲述类的继承、接口以及多态的相关知识。8.1 继承8.2 接口8.
2、3 多态性8.4 使用Me、MyBase和MyClass关键字8.5 可视化继承通过继承,可以直接基于系统中现有的类创建新类。现有的类称为基类,也可以称为父类、超类。新创建的类称为派生类,也可以称为子类。派生类继承了基类中的所有属性、方法、事件,并且可以对基类进行扩展。VB.NET中使用Inherits语句来创建派生类,该语句使得当前类继承指定类的所有非私有成员,其基本语法格式如下。Class 派生类名Inherits 基类名类成员End ClassStep1:新建一个Windows Form应用程序工程,命名为“ProfessorClass”。Step2:单击菜单栏中的【项目】【添加类】命令
3、,建立一个名为Teacher的类,作为基类。下面代码创建了基类Teacher。1 Public Class Teacher2 Private teaName As String3 Private teaBirthDate As Date4 Private teaNative As String5 6 Public Property Name()As String7 Get8 Return teaName9 End Get10 Set(ByVal value As String)11 teaName=value12 End Set13 End Property14 15 Public Prope
4、rty BirthDate()As Date16 Get17 Return teaBirthDate18 End Get19 Set(ByVal value As Date)20 teaBirthDate=value21 End Set22 End Property23 24 Public Property Native()As String25 Get26 Return teaNative27 End Get28 Set(ByVal value As String)29 teaNative=value30 End Set31 End Property32 End ClassStep3:创建T
5、eacher类的派生类Professor。可以单击菜单栏中的【项目】【添加类】命令来添加一个类,也可以将该类与Teacher类放在同一个文件中。1 Class Professor2 Inherits Teacher3 Private proDate As Date4 Private proSalary As Double5 6 Public Property EngageDate()As Date7 Get8 Return proDate9 End Get10 Set(ByVal value As Date)11 proDate=value12 End Set13 End Property14
6、 15 Public Property Salary()As Double16 Get17 Return proSalary18 End Get19 Set(ByVal value As Double)20 proSalary=value21 End Set22 End Property23 End ClassVB.NET还提供NotInheritable和MustInherite修饰符对继承进行控制。NotInheritable修饰符表示该类不允许被继承,即指定该类不能作为基类。不能被继承的类有时也称为密封类 MustInherite修饰符表示该类必须被继承,即必须作为基类而不能用于创建实例
7、,必须作为基类的类有时也被称为抽象类。接口与类很相似,也定义了一系列属性、方法和事件。但与类不同的是,接口并不提供实现。它们由类来实现,并从类中被定义为单独的实体。接口在面向对象设计中发挥着非常重要的作用,我们可以使用接口来表示一种约定,实现接口的类必须严格按其定义来实现接口的每个方面。在应用程序要求很多可能不相关的对象类型以提供某种功能的情况下,接口的适用性更强。接口比类更灵活,因为可以定义单个实现来实现多个接口。在无需从基类继承实现的情况下,接口更好。在无法使用类继承的情况下接口是很有用的。例如,结构无法从类继承,但它们可以实现接口。VB.NET允许使用Interface语句来定义接口,其
8、基本语法格式如下。修饰符Interface接口名 Property成员名 Function成员名 Sub成员名 Event成员名 Interface成员名 Class成员名 Structure成员名End Interface下面的代码定义了一个接口IConnectable。1 Interface IConnectable 2 Function Connect()As Boolean 3 Sub Disconnect()4 End Interface接口可以继承其他接口,因此可以使用接口来定义层次结构表示实体之间的相互关系。下面的代码定义了ITimedConnectable接口,通过引入连接超时
9、的概念扩展了IConnectable接口。1 Interface ITimedConnectable 2 Inherits IConnectable 3 Sub TimeOut(ByVal millisecs As Long)4 End Interface类和结构都可以用于实现接口,甚至还可以实现多个接口。使用Implements语句实现接口的类或结构的语法格式如下。Class(或Structure)类名(或结构名)Implements 接口1Implements 接口n 具体实现代码End Class(或End Structure)在类或者结构内部实现接口中的成员时也需要使用Implemen
10、ts语句,指明要实现的接口成员。接口成员的规范由接口名称(必须在类或结构名称后的implements语句中指定)、点号和要实现的成员函数、属性或事件的名称组成。下面代码显示了如何声明一个名为Sub1的用于实现接口方法的子例程。1 Class Class1 2 Implements interfaceclass.interface2 3 4 Sub Sub1(ByVal i As Integer)Implements interfaceclass.interface2.Sub1 5 End Sub 6 End Class多态就是对象随着程序执行而使其形式发生改变的能力。派生类在继承基类时,会得到
11、基类所有的属性,字段和方法。但有时派生类中定义的特有属性和方法往往与基类中继承得到的属性和方法同名。VB.NET允许在子类中使用与基类的属性或方法同名的属性及方法,即允许在一个类中,相同名字的属性或方法能够通过不同的代码,完成不同的功能,这样就实现了类的多态性。要在派生类中使用与基类类属性或方法同名但功能不同的属性或方法,一个简单的方法是把原来基类中定义的属性或方法覆盖,换成派生类的相关代码,这称为重写。具体做法是,基类中允许重写的属性和方法使用关键字Overridable声明,而在派生类中使用关键字Overrides定义重写的属性及方法。下面代码中,Manager类重写了其基类Employe
12、e类中的CalSalary方法。1 Class Employee2 Public Overridable Function CalSalary(ByVal HoursWorked As Decimal,_3 ByVal PayRate As Decimal)As Decimal4 Return HoursWorked*PayRate5 End Function6 End Class7 8 Class Manager9 Inherits Employee10 Private BonusRate As Decimal=1.511 Public Overrides Function CalSalar
13、y(ByVal HoursWorked As Decimal,_12 ByVal PayRate As Decimal)As Decimal13 Return HoursWorked*PayRate*BonusRate14 End Function15 End Class重写的成员要求与基类成员具有相同的参数,因此在某些情况下,如需要使用不同类型或者不同个数的参数完成类似的功能,重写就不适用了。这个时候,就要用到重载。重载是在一个类中用相同的名称但是不同的参数类型创建一个以上的过程、实例构造函数或属性。重载的方法使用相同的名字,但使用不同的参数。例如,定义类DispalayData用于显示不同
14、类型的数据,可以定义多个重载的Display方法。1 Class DisplayData2 Overloads Sub Display(ByVal theChar As Char)3 End Sub4 5 Overloads Sub Display(ByVal theInteger As Integer)6 End Sub7 8 Overloads Sub Display(ByVal theDouble As Double)9 End Sub10 End Class重载成员必须具有不同的特征,下面的项不能用作区分特征。应用于成员或成员参数的修饰符,如ByVal或ByRef。参数名。过程的返回类
15、型。重载时关键字Overloads是可选的,但如果任一重载成员使用了该Overloads关键字,则其他所有同名重载成员也必须指定该关键字。Me关键字提供了一种引用当前正在其中执行代码的类或结构的特定实例的方法。MeMe的行为类似于引用当前实例的对象变量或结构变量。在向另一个类、结构或模块中的过程传递关于某个类或结构的当前执行实例的信息时,使用Me尤其有用。MyBase关键字的行为类似于这样的对象变量:它引用类的当前实例的基类。MyBase通常用于访问在派生类中被重写或隐藏的基类成员。例如,MyBase.New用于从派生类构造函数中显式调用基类构造函数。MyBase关键字用于在派生类中调用基类的
16、非私有成员,尤其是在需要使用基类中被派生类隐藏了的方法时MyBase关键字十分有用。MyClass关键字的行为类似于这样的对象变量:它引用最初实现的类的当前实例。MyClass类似于Me,但在调用MyClass中的每个方法和属性时,可将此方法或属性当作NotOverridable中的方法或属性对待。因此,方法或属性不受派生类中重写的影响。可视化继承是VB.NET提供的新的继承方式,一般指的是对窗体的继承。在VB.NET中,窗体本身就是一个类,如果要实现窗体继承,可以通过生成一个基类窗体,然后使用Inherits语句就可以在新窗体中实现对基类窗体的继承。这个过程也可以通过可视化编译环境来实现。S
17、tep1:新建一个Windows Form窗体应用程序,命名为“BaseForm”。Step2:设计窗体。Step3:鼠标双击Button控件,编写其Click事件过程。1 Public Class BaseForm 2 3 Private Sub btnProtected_Click(ByVal sender As System.Object,ByVal e As System.EventArgs)Handles btnProtected.Click 4 MsgBox(Protected的按钮)5 End Sub 6 7 Private Sub btnPrivate_Click(ByVal
18、sender As System.Object,ByVal e As System.EventArgs)Handles btnPrivate.Click 8 MsgBox(Private的按钮)9 End Sub 10 End ClassStep4:将应用程序类型修改为类库。在【解决方案资源管理器】窗口中双击【My Project】或者右击【BaseForm】项目名称,在打开的右键菜单中单击【属性】,打开项目属性设置窗口,并将应用程序类型修改为类库。Step5:单击菜单栏中的【生成】【生成BaseForm】命令,在binRelease文件夹下,会生成BaseForm.dll文件。至此,基类窗体
19、的设计就完成了。下面通过集成环境来创建一个派生的窗体。Step6:单击菜单栏中的【文件】【添加】【新建项目】命令,添加一个新建的Windows Form窗体应用程序工程,并命名为“InheritanceForm”。Step7:单击菜单栏中的【项目】【添加类】命令,打开【添加新项-InheritanceForm】窗口,在该窗口的【模板】列表框中选择【继承的窗体】,并在【名称】文本框中输入“InheritanceForm”。Step8:单击【添加】按钮后,在随后打开的【继承选择器】窗口中,选择要继承的窗体。此时,窗体界面如下。Step9:双击派生窗体上的【保护】按钮,编写其Click事件过程。1
20、Public Class InheritanceForm 2 Private Sub btnProtected_Click(ByVal sender As System.Object,ByVal e As System.EventArgs)Handles btnProtected.Click 3 MsgBox(派生的保护按钮)4 End Sub 5 End ClassStep10:右击【解决方案资源管理器】窗口中的【InheritanceForm】项目,在打开的右键菜单中单击【设为启动项目】。双击【My Project】,在打开的项目属性设置窗口中的【启动窗体】下拉列表框中选择【InheritanceForm】。