VFP学习、开发漫谈 (13)
今天,先聊一聊有关变量的作用域。首先,作用域的概念主要是针对同名变量来说的。为了处理不同模块中同名变量的冲突问题,才出现了变量的作用域概念。
我们都知道,VFP 中的变量分为全局变量(Public)、私有变量(Private)和局部变量(Local)三种。全局变量很好理解,它的作用域是应用程序中的所有模块(表单、报表、程序等)。私有变量的作用域是当前程序及子程序(函数)。局部变量的作用域是当前程序(函数)。全局变量的作用域最大,局部变量的作用域最小。在满足需要的前提下,应尽可能缩小变量的作用域。若不声明变量,则变量为私有变量。建议在程序的起始行,声明本模块要引用的所有变量。
“作用域”是一个相对概念。比如:在主程序(main.prg)中使用 Public 与使用 Private 定义的变量其作用域是相同的。因为主程序本身位于应用程序的最“顶层”,其调用的所有模块都可以看作是主程序的“子程序”,所以在主程序中定义的私有变量其作用域也是全局的。再比如,若当前程序并没有调用其他程序,则 Private 与 Local 变量的作用域也相同。
严格来说,将 Public 和 Local 命令描述为“定义”变量,而将 Private 命令描述为“声明”变量比较准确。如:Public A 会定义一个初值为 .f. 的变量,同时声明其作用域为全局,此时 TYPE('a')='L',说明变量 a 已经存在。而 Private A 仅声明变量 a 为私有变量,此时 TYPE('a')='U',说明变量 a 并不存在,若要在后面的代码中引用该变量,还必须为其赋初值。这是初学者经常犯的错误。
VFP 并没有 VB 那样的窗口变量,即:在表单的所有事件和方法中均可引用,但完全可以通过为表单添加自定义属性来解决。表单的自定义属性不但可以是字符、数值、逻辑、日期等普通类型数据,还可以是对象或数组类型。我们既可以在设计模式下,通过菜单“New Property”来添加属性,也可以在运行时通过命令“THISFORM.AddProperty(属性名,属性值)”随时添加。
在设计模式下,为表单添加数组属性时,需要在 Name 文本框中输入数组名和下标,如:a[5]。在运行时,使用 THISFORM.AddProperty('a[5]')为表单添加数组属性。
需要指出的是:VFP 可以为任何对象添加自定义属性,并不仅限于表单。甚至还可以通过为 _Screen 添加属性的方式来代替全局变量的使用。
我忽然想到一个问题:如何判断变量 a 是“普通变量”还是“数组变量”?是“字段变量”还是“内存变量”?
对于第 1 个问题,可以使用 TYPE()函数来解决。若 TYPE('a[1]')='U',或 TYPE('a',1)#'A',则说明 A 是普通变量,否则为数组变量。
对于第 2 个问题,可以使用 FIELD()函数来解决,若 EMPTY(FIELD('a')),则 a 为内存变量,否则 a 为当前工作区的字段变量。
这里再介绍一下 TYPE()函数与 VARTYPE()函数的区别,总结如下:
1. 二者都可以检测变量或表达式的数据类型,但 TYPE()需将参数放在引号内,而 VARTYPE()不用
2. 二者的功能并不完全相同,TYPE()的功能更强一些,可完全取代 VARTYPE(),反之则不一定
3. 当无法获得参数的数据类型时,TYPE()不会报错,而是返回 U,但 VARTYPE()有时会报错。以下两行命令会报错:
? VARTYPE(THISFORM.txtID.Value) && 假设对象 txtID 不存在
? VARTYPE(A[1]) && 假设 A 不是数组,或不存在
4. 利用 TYPE() 可判断一个变量是不是数组,VARTYPE() 无此功能:
? TYPE('A[1]') && 若返回 U,则 A 不是数组,否则,A是数组
? TYPE('A',1) && 若返回 A,则 A 是数组,否则,A不是数组
5. 二者对 NULL 值的处理稍有不同:
i = 10
i = NULL
? TYPE('i') && 返回 N
? VARTYPE(i) && 返回 X
? VARTYPE(i,.t.) && 返回 N
我一般使用 TYPE()函数的情况比较多,很少使用 VARTYPE()。
在实际应用中,应尽可能少用全局变量,并注意即时释放。如:在表单的 Load 事件中,使用 Public gcName 定义了一个全局变量 gcName,那么在表单的 Destroy 或 Unload 事件中,注意使用 Release gcName 将其释放。若使用 Release All释放内存变量,一定要加 Extended 选项,即:Release All Extended。否则,全局变量不会被释放。
[ 本帖最后由 liuxingang28 于 2014-3-27 15:17 编辑 ]