|
End Sub Sub DisplayInt(ByVal theInteger As Integer) '''' Add code that displays Integer data. End Sub Sub DisplayDouble(ByVal theDouble As Double) '''' Add code that displays Double data. End Sub 因为重载提供了对可用数据类型的选择,所以它使得属性或方法的使用更为容易。例如,可以用下列任一代码行调用前面讨论过的重载 Display 方法: Display("9"C) '''' Call Display with a literal of type Char. Display(9) '''' Call Display with a literal of type Integer. Display(9.9R) '''' Call Display with a literal of type Double. 在运行时,Visual Basic .NET 根据指定参数的数据类型调用正确的过程。 注意 重载、重写和隐藏操作是容易混淆的类似概念。有关更多信息,请参见介绍 Visual Basic 中的对象。 重载规则 用同样名称添加两个或更多属性或方法可以创建类的一个重载成员。除了重载派生成员,每一个重载成员必须具有不同的参数列表。当重载属性或过程时,下面的项不能用作区分特征: 应用于成员或成员参数的修饰符,如 ByVal 或 ByRef。 参数名 过程的返回类型 重载时关键字 Overloads 是可选的,但如果任一重载成员使用了该 Overloads 关键字,则其他所有同名重载成员也必须指定该关键字。 派生类可以用具有相同参数和参数类型的成员重载继承成员,该过程称作“按名称和签名隐藏”。如果按名称和签名隐藏时使用了 Overloads 关键字,将使用该成员的派生类实现而非基类中的实现,并且该成员的所有其他重载对于该派生类的实例都将可用。 如果用一个具有相同参数和参数类型的成员重载继承成员时,省略了 Overloads 关键字,则该重载称为“按名称隐藏”。按名称隐藏替代一个成员的继承实现,使所有其他重载对于该派生类及由其派生的类的实例都不可用。 Overloads 和 Shadows 修饰符不能同时被同一个属性或方法所使用。 示例 下面的示例创建接受美元金额的 String 或 Decimal 表示形式并返回包含销售税的字符串的重载方法。 使用此示例创建重载方法 打开新项目,添加名为 TaxClass 的类。 向 TaxClass 类中添加下面的代码。 Public Class TaxClass Overloads Function TaxAmount(ByVal decPrice As Decimal, _ ByVal TaxRate As Single) As String TaxAmount = "Price is a Decimal. Tax is $" & _ (CStr(decPrice * TaxRate)) End Function Overloads Function TaxAmount(ByVal strPrice As String, _ ByVal TaxRate As Single) As String TaxAmount = "Price is a String. Tax is $" & _ CStr((CDec(strPrice) * TaxRate)) End Function End Class 向窗体中添加下面的过程。 Sub ShowTax() Const TaxRate As Single = 0.08 '''' 8% tax rate Dim strPrice As String = "64.00" '''' $64.00 Purchase as a String. Dim decPrice As Decimal = 64 '''' $64.00 Purchase as a Decimal. Dim aclass As New taxclass() ''''Call the same method with two diferent kinds of data. MessageBox.Show(aclass.TaxAmount(strPrice, TaxRate)) MessageBox.Show(aclass.TaxAmount(decPrice, TaxRate)) End Sub 向窗体中添加按钮,并从该按钮的 Button1_Click 事件调用 ShowTax 过程。 运行该项目并单击窗体上的该按钮,以测试重载 ShowTax 过程。 在运行时,编译器选择与所用参数匹配的适当重载函数。单击该按钮时,首先将使用类型为字符串的 Price 参数调用被重载的方法,并显示信息:“Price is a String.Tax is $5.12”。第二次将使用类型为 Decimal 的值调用 TaxAmount,并显示信息“Price is a Decimal.Tax is $5.12”。 重写属性和方法 派生类继承其基类中定义的属性和方法。这很有用,因为它意味着当这些项适合于您要使用的类时,可以重用它们。如果继承成员不能按原样使用,则可以选择使用 Overrides 关键字定义新实现,假设基类中的属性或方法使用 Overridable 关键字标记,或通过重新在派生类中定义成员来隐藏该成员。 实际上,重写的成员经常用于实现多态性。有关多态性的更多信息,请参见多态性。 下列规则适用于重写方法。 仅可重写在其基类中用 Overridable 关键字进行标记的成员。 默认情况下,属性和方法为 NotOverridable。 重写的成员必须具有与从基类继承的成员相同的参数。 成员的新实现可通过在方法名称前指定 MyBase 来调用父类中的原始实现。 注意 重载、重写和隐藏操作是容易混淆的类似概念。有关更多信息,请参见介绍 Visual Basic 中的对象。 示例 假设您要定义类以处理工资单。您可以定义一个一般 Payroll 类,其中包含计算普通周工资单的 RunPayroll 方法。然后可将 Payroll 用作更专用的 BonusPayroll 类的基类,分发雇员奖金时可使用该 BonusPayroll 类。 BonusPayroll 类可继承并重写在基类 Payroll 中定义的 PayEmployee 方法。 下面的示例定义基类 Payroll 和派生类 BonusPayroll,该派生类重写继承方法 PayEmployee。过程 RunPayroll 创建 Payroll 对象和 BonusPayroll 对象,然后将其传递给函数 Pay,该函数执行这两个对象的 PayEmployee 方法。 Const BonusRate As Decimal = 1.45 Const PayRate As Decimal = 14.75 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 MessageBox.Show("Normal pay is: " & _ PayrollItem.PayEmployee(HoursWorked, PayRate)) MessageBox.Show("Pay with bonus is: " & _ BonusPayrollItem.PayEmployee(HoursWorked, PayRate)) End Sub 重写修饰符 可使用 NotOverridable 和 MustOverride 修饰符控制如何在派生类中重写属性和方法。 NotOverridable 修饰符定义无法在派生类中重写的基类的方法。所有方法都为 NotOverridable,除非用 Overridable 修饰符进行标记。当不希望允许在派生类中再次重写 overridden 方法时,可使用 NotOverridable 修饰符。 用 MustOverride 修饰符定义的方法在基类中没有实现,必须在派生类中实现。包含 MustOverride 方法的类必须使用 MustInherit 修饰符进行标记。 示例 MustInherit Class BaseClass Public MustOverride Sub aProcedure() End Class Class DerivedClass Inherits BaseClass Public NotOverridable Overrides Sub aProcedure() '''' Override a procedure inherited from the base class '''' and mark it with the NotOverridable modifier so that '''' it cannot be overridden in classes derived from this class. End Sub End Class 用集合管理对象 集合提供一种管理各种对象的理想方法。可以在集合中添加和移除对象、根据索引或键检索它们,以及使用 For Each...Next 语句循环通过集合中的项。但是,集合极强的灵活性可能会破坏类的可靠性。 可以采用三种常规方法使用集合来实现对象管理。请考虑组织小部件并将其公开给客户端组件的组件。若要使用集合实现此组件,则可以: 在 WidgetRepository 类中,将 Widgets 变量声明为集合,并使其成为公共变量。 通过继承 CollectionBase 类来实现您自己的 WidgetsCollection 类。授予 WidgetRepository 类一个 WidgetsCollection 类的属性。 通过编写适当的类和方法在 WidgetRepository 类中实现集合类型功能来实现此功能。如果要在类中拥有集合类型功能,但无法从任何集合类型类继承时,这种方法最为有用。例如,如果希望从集合类之外的其他类继承。 可以向类中添加集合以管理可能由该类公开的对象。实现此功能的最简单的方法是将类型为 Collection 的公共变量添加到类中。请考虑名为 WidgetRepository 的假设类,该类管理和公开小部件。可以创建 WidgetCollection 变量作为小部件的集合,如下面的示例中所示: Public Class WidgetRepository Public WidgetCollection As New Collection() '''' Insert code to implement additional functionality. End Class 现在此类有一个公共集合,可以向其添加 Widget 对象。但这种方法有一些问题。首先,此集合不是强类型的。如果执行下面代码将会发生什么呢? Dim myString As String = "This is not a Widget object!" WidgetCollection.Add(myString) 答案是它将被添加到该集合中,即使它不是 Widget 对象。事实上,任何对象都可添加到集合中,不管是什么类型。如果接着尝试使用 For Each...Next 语句处理小部件,问题随即发生,如下所示: Dim aWidget As Widget For Each aWidget in WidgetCollection '''' Insert code to process Widgets Next 在该示例中,程序在运行时引发 ArgumentException 异常,因为集合的一个成员不是 Widget 类型。 另一个问题涉及公开集合的成员。因为 Collection 类接受并返回 Object 类型的成员,所以当 Option Strict 语句为 On 时,无法使用集合所管理的对象的任何功能。若要将该集合提供的引用转换为适当的类型,则必须改用 CType 函数,如下所示: Dim myWidget As Widget MyWidget = CType(WidgetCollection(1), Widget) 请注意,当 Option Strict 为 Off 时,将隐式执行转换,尽管晚期绑定将导致性能的下降。 如果需要避免这些问题,或您的类要求更可靠类型的集合,应考虑使用 CollectionBase 创建您自己的集合类。有关详细信息,请参见演练:创建您自己的集合类。 事件和事件处理程序 Visual Studio 项目很容易被看作一系列顺序执行的过程。事实上,多数程序都是事件驱动的,即执行流程是由外界发生的事件所确定的。 事件是一个信号,它告知应用程序有重要情况发生。例如,用户单击窗体上的某个控件时,窗体引发一个 Click 事件并调用一个处理该事件的过程。事件还允许在不同任务之间进行通信。比方说,您的应用程序脱离主程序执行一个排序任务。若用户取消这一排序,应用程序可以发送一个取消事件让排序过程停止。 事件术语和概念 本节描述 Visual Basic .NET 中与事件一起使用的术语和概念。 声明事件 使用 Event 关键字在类、结构、模块和接口内部声明事件,如以下示例所示: Event AnEvent(ByVal EventNumber As Integer) 引发事件 事件就像是通告已发生重要情况的消息。广播该消息的行为叫引发事件。在 Visual Basic .NET 中,使用 RaiseEvent 语句引发事件,如以下示例所示: RaiseEvent AnEvent(EventNumber) 必须在声明事件的范围内引发事件。例如,派生类不能引发从基类继承的事件。 事件发送器 任何能引发事件的对象都是事件发送者,也称事件源。窗体、控件和用户定义的对象都是事件发送器。 事件处理程序 事件处理程序是相应事件发生时调用的过程。您可以将任何有效子例程用作事件处理程序。可是,不能将函数用作事件处理程序,因为它不能将值返回给事件源。 Visual Basic 采用标准命名约定对事件处理程序进行命名,即用下划线把事件发送器和事件的名称组合起来。例如,名为 button1 的按钮的单击事件应命名为 Sub button1_Click。 注意 建议使用此命名约定定义您自己事件的事件处理程序。但这并不是必选的方法。您可以使用任何有效的子例程。 关联事件与事件处理程序 在事件处理程序生效之前,首先必须使用 Handles 或 AddHandler 语句将它与事件关联。 WithEvents 语句和 Handles 子句提供了陈述性指定事件处理程序的方法。WithEvents 所声明对象引发的事件可以由任何子例程用命名此事件的 Handles 子句来处理。虽然 Handles 子句是关联事件与事件处理程序的标准方法,它仅限于在编译时关联事件与事件处理程序。 AddHandler 和 RemoveHandler 语句要比 Handles 子句更灵活。它们允许在运行时动态地将事件与一个或更多的事件处理程序连接或者断开,而并不要求使用 WithEvents 来声明对象变量。 在某些情况下,比如使用窗体或控件所关联的事件,Visual Basic .NET 会自动引出一个空事件处理程序并将它与某个事件关联。例如,在设计模式下双击窗体上的命令按钮时,Visual Basic .NET 上一页 [1] [2] [3] 下一页 [C语言系列]NET 中C#的switch语句的语法 [系统软件]托拽Explore中的文件到VB.net的窗口 [系统软件]Boost库在XP+Visual C++.net中的安装 [常用软件]新配色面板:Paint.Net3.0RC1官方下载 [常用软件]用内建的“Net Meeting”聊天 [VB.NET程序]Henry的VB.NET之旅(三)—共享成员 [VB.NET程序]Henry的VB.NET之旅(二)—构造与析构 [VB.NET程序]Henry的VB.NET之旅(一)—失踪的窗体 [VB.NET程序]在托盘上显示Balloon Tooltip(VB.NET) [VB.NET程序]Henry手记-VB.NET中动态加载Treeview节点(二)
|