2.5 过程
2.5.1 过程概述
一个应用程序由若干模块组成,而每个模块又由若干个更小的代码片段组成,组成这些模块的代码片段被称为过程。通过过程,可以将整个程序按功能进行分块,每个过程用来完成一项特定的功能。使用过程来组织代码,可以增强代码的条理性和可维护性。
显然,过程创建于一个类或一个模块内。既可以从创建过程的同一个类或模块中调用它,也可以从不同的类和模块调用过程,这取决于创建过程时访问修饰词的使用。访问修饰词决定一个过程可以被调用的范围。下面列出VB.NET中所有的有效的访问修饰词。
· Public:可以从应用程序的任何类或模块调用的过程。
· Private:只能从声明过程的类或模块调用的过程。
· Shared:不与一个类的实例相联系的过程。
· Protected:可以从声明过程的类或模块或从派生的类调用的过程。
· Friend:可以从包含其声明的应用程序的任何类或模块调用的过程。
· Protected Friend:拥有Protected和Friend访问的过程。
当一个复杂的应用程序划分成过程时,代码更灵活并且更容易维护和调试。使用过程编程的优点可以总结为以下几点。
· 消除了重复语句行
· 使程序更易阅读
· 简化了程序开发
· 其他程序可重复使用该通用过程
· 扩展VB.NET语言
过程的基本分类,读者也应该了解。VB.NET中过程的基本分类如下:
1.事件过程
当Visual Basic中的对象对于各事件的发生做出认定时,便自动用对应于事件的名字调用该事件的过程。因为名字在对象和代码之间建立了联系,所以事件过程是附加在窗体和控件上的。
(1)一个控件的事件过程将控件的实际名字(在Name属性中规定的)、下画线(_)和事件名组合起来。
例如,如果希望在单击了一个名为btnPlay的命令按钮之后,这个按钮会调用事件过程,则要使用btnPlay_Click过程。
(2)一个窗体事件过程将窗体的名字空间、下画线和事件名组合起来。如果希望在单击窗体之后,窗体会调用事件过程,则要使用Form_Click过程(和控件一样,窗体也有唯一的名字,但事件过程不能使用这些名字)。
虽然用户可以自己编写事件过程,但使用Visual Basic提供的过程会更方便,这个过程自动将正确的过程名包括进来。从“对象框”中选择一个对象,从“过程框”中选择一个过程,就可在“代码编辑器”窗中选择一个模板。在开始为控件编写事件过程之前先设置控件的Name属性,这样可以避免在编译时产生一定的错误隐患。如果对控件附加一个过程之后又更改控件的名字,那么也必须更改过程的名字,以符合控件的新名字。否则,Visual Basic无法使控件和过程相符。过程名与控件名不符时,过程就成为通用过程。
2.函数过程
函数过程用来完成特定的功能并返回相应的结果。在事件或其他过程中可按名称调用函数。函数过程能够接收参数,并且总是以该函数名返回一个值。这类过程一般用于完成计算任务。
3.子过程
子过程是没有返回值的函数。在事件过程或其他过程中可按名称调用子过程。子过程能够接收参数,并可用于完成过程中的任务并返回一些数值。但是,与函数过程不同,子过程不返回与其特定子过程名相关联的值。子过程一般用于接收或处理输入数据、显示输出或设置属性。
4.属性过程
属性过程用来创建和操作程序中用户定义的属性。这是一种有用的、在某种程度上相当高级的特性,它使得用户能够定制现有的VB.NET控件并通过创建新的对象、属性和方法来扩展VB.NET语言。
5.通用过程
通用过程告知应用程序如何完成一项指定的任务。一旦确定了通用过程,就必须由专有应用程序来调用。反之,在响应用户引发的事件或系统引发的事件而调用事件过程之前,事件过程通常总是处于空闲状态。建立通用过程就是为了将几个不同的事件过程所要执行的公共语句“提”出来。将公共语句放入一个分离开的过程(通用过程)并由事件来调用它,这样一来就不必重复代码,也容易维护应用程序。面向过程的编程思想就是每个事件对应相应的过程,一般来说,过程的大小应在60至200行代码之间,如果小于这个范围,就要考虑这个过程是否需要单独提出来,如果大于这个范围,就应当考虑是否应将大的过程细化,一个好的程序风格总会看到其层次关系,也就是过程既有它需要调用的子过程,也有调用它的父过程。
在标准模块中可以创建三种类型的通用过程,即函数过程、子过程和属性过程。
2.5.2 Sub过程
Sub过程是在响应事件时执行的代码块,可以在模块和类中创建。Sub过程的默认访问修饰词是Public,表示Sub过程可以从一个应用程序的任何地方调用。Sub过程的语法如下:
[{Private|Public|Friend|Protected|Protected Friend}] Sub subname([arguments list]) [statements] [Exit Sub] [statements] End Sub
其中,
[{Private|Public|Friend|Protected|Protected Friend}]代表Sub过程的访问修饰词。如果不指定任何访问修饰词,默认为Public。
Sub表示该过程是一个Sub过程。
subname代表过程的名字。过程名可以任意指定,但是要满足VB.NET变量名命名规则,并且在同一模块中不得重复。给过程命名时,一般要尽量能反映出这个过程的作用。
arguments list是参数列表。Sub过程声明时的参数称为“形式参数”,即“形参”。过程可以没有形参,也可以有一个或多个形参,多个形参之间用逗号隔开。如果Sub过程不使用任何参数,则Sub语句必须包括括号的一个空集。如果有参数则声明过程的参数与声明变量的规则一样,还需要指明该参数是按值传递还是按地址传递。关于按值传递和按地址传递在后面的参数传递一节有所介绍。
statements是过程中的执行语句块。
Exit Sub表示强制退出Sub过程。
End Sub表示Sub过程的结束。
每次调用过程都会执行Sub和End Sub之间的statements。可以将子过程放入标准模块、类模块中。按照默认的规定,所有模块中的子过程为Public(公用的)意味着在应用程序中可随处调用它们。
示例如下:
Sub subN() Dim a As Integer = 15 Dim b As Integer = 3 Dim c As Integer = a + b End Sub
上例中声明了一个无参数的Sub过程,这个过程用来计算整型数据a和b相加的结果,并保存在变量c中。
再看下面的一个例子,例中创建了一个Sub过程名称为add,过程声明了两个形参a和b,并指明为值传递的方式,a和b的值由程序调用过程的时候传入,然后计算a加b并将值赋给过程内部的变量c,并调用通用过程Show ()显示它的值。
Sub add(ByVal a, ByVal b) 'add过程,参数为a和b Dim c As Integer c = a + b MessageBox.Show(c) End Sub
2.5.3 Function过程
VB.NET包含内置的或内部的函数,如MsgBox,CStr等。此外,还可用Function语句编写自己的Function过程。函数过程的语法如下:
[{Private|Public|Friend|Protected|Protected Friend}] Function functionName([arguments list]) [statements] [Exit Sub] [statements] End Sub
与Sub过程一样,Function过程也是一个独立的过程,可读取参数、执行一系列语句并改变其参数的值。与Sub过程不同的是,Function过程可返回一个值到调用的过程。在Sub过程与Function过程之间有如下三点区别。
(1)一般来说,语句或表达式的右边包含函数过程名和参数(returnvalue=function),这就调用了函数。
(2)每个Function过程都具有数据类型,就和每个变量都具有数据类型一样。该数据类型由Function语句中的As子句指定,并且它确定返回值的类型(如果没有As子句,默认的数据类型为Object)。
(3)可以给functionName赋一个值,即为返回的值。
Function过程返回一个值时,该值可成为表达式的一部分。例如,下面代码是已知两个整数,计算它们乘积的函数。
Function product(ByVal A As Integer, ByVal B As Integer) As String product = Math.Sqrt(A * B) End Function
在Visual Basic中调用Function过程的方法和调用任何内部函数的方法是一样的,如下:
Me.TextBox3.Text=CStr(product(CInt(Me.TextBox1.Text),CInt(Me.TextBox2.Text )))
上例中是采用给Function过程名赋一个值来返回值的,也可以通过Return语句返回值。例如,可修改上例如下:
Function product(ByVal a As Integer, ByVal b As Integer) As Integer Return a * b End Function
2.5.4 调用过程
在创建了一个过程(或函数)之后,只有调用该过程(或函数),才能使用它的功能,也才能体现出定义这个过程(或函数)的价值。
1.调用Sub过程
调用一个Sub过程的语法如下:
[Call] < subname > ([arguments list])
其中的arguments list是实际参数列表,含多个参数时可用“,”逗号隔开。
与Function过程不同,在表达式中,Sub过程不能用其名字调用,调用Sub过程的是一个独立的语句。Sub过程还有一点与函数不同,它不会用名字返回一个值。但是,与Function过程一样,Sub过程也可以修改传递给它们的任何变量的值。关于Function过程将会在下一节介绍。
调用语句必须提供所有参数的值,并且必须用括号将参数列表括起来。如果未提供任何参数,则也可以选择省略括号。Call关键字的使用也是可选的。
2.调用函数过程
通过将函数名与任何所需的参数(参数是函数用来进行计算的数据)一起置于一条程序语句中,可以执行或调用该函数。使用函数过程与使用内置函数(如Cint,CStr或MessageBox.Show等)的方法完全相同。
返回值是Function过程最重要的功能,要使用函数的返回值,必须使用这样的方法,即把函数用于赋值语句、表达式中,或者将其作为实际参数来调用其他过程。这时可以使用函数名调用,并且必须用括号把实参括起来。
调用函数的语法如下:
<functionName> ([arguments list])
或者将函数赋值给调用代码中的变量,语法如下:
ReturnValue = <functionName> ([arguments list])
3.调用其他模块中的过程
在工程中的任何地方都能调用类模块或标准模块中的公用过程。可能需要指定这样的模块,它包含正在调用的过程。调用其他模块中的过程的各种技巧,取决于该过程是在类模块中还是在标准模块中。
在类模块中调用过程要求调用与过程一致并且指向类实例的变量。例如,DemoClass是类Class1的实例,过程调用代码如下:
Dim DemoClass As New Class1 DemoClass.SomeSub
在引用一个类的实例时,不能用类名作限定符。必须首先声明类的实例为对象变量(在这个例子中是DemoClass)并用变量名引用它。
标准模块中的过程如果过程名是唯一的,则不必在调用时加模块名。无论是在模块内,还是在模块外调用,结果总会引用这个唯一过程。如果过程仅出现在一个地方,这个过程就是唯一的。如果两个以上的模块都包含同名的过程,那就有必要用模块名来限定了。在同一模块内调用一个公共过程就会运行该模块内的过程。例如,对于Module1和Module2中名为CommonName的过程,从Module2中调用CommonName则运行Module2中的CommonName过程,而不是Module1中的CommonName过程。从其他模块调用公共过程名时必须指定那个模块。如在Module1中调用Module2中的CommonName过程,要用下面的语句。
Module2.CommonName(arguments)
下面以实例说明Sub过程的声明和调用。