4. Procedures in VBScript
为支持代码复用,VBScript提供了过程Sub和函数Function两种语法结构。在C/C++中并没有过程一说,不过VBScript中的过程其实跟函数差别并不大,可以看作是void型的函数。由于两者的差异很小,本文中多数讨论,对两者都适用。
- 过程Sub
一个过程由
Sub xxx(x,y,..)
End Sub
定义。过程在End Sub处结束,但也可以在中间由Exit Sub退出。
- 函数Function
一个函数由
Function xxx(x, y,…)
End Function
定义。函数在End Function处结束,但也可以在中间由ExitFunction退出。与C/C++不同的是,VBScript没有return语句,函数的返回值由函数名带回去。与VB不同的是,由于VBScript的无类型特性,不可以申明函数返回值的类型,variant声明也是不允许的。关于函数的例子,在第一部分就就给出了一个获取本机IP的例子,读者可以参考那一部分。注意函数的返回值是由
GetIP = IP
带回的。在函数调用时,必须使用括号,否则函数将成为一个过程,并且得不到返回值。
与C/C++灵活的函数用法形成对照的是,VBScript中的过程和函数的用法很弱。为许多VBScript的爱好者诟病的不足之一是,VBScript的函数和过程不支持可变参数。尤其令人气愤的是,在VBScript中存在大量系统函数调用是允许可变参数的。这种不一致性给编程人员带来额外的理解和记忆上的麻烦。好在失望之余,还存在一些不太直观的补救方法。其一是可以仅为函数指定一个形式参数,且将这个参数定义为数组。由于VBScript的无类型特性,因此数组的各个元素可以携带不同类型的数据(指子类型)。请看示例:
首先要定义两个辅助函数IsMissing和Valid。IsMissing是VB中支持的函数,但在VBScript中,我们需要自已来定义。
Function Valid(arrayVar,arrayIndex)
If ubound(arrayVar)<arrayIndex or lbound(arrayVar)>arrayIndex Then
Valid=Empty
Else
Valid=arrayVar(arrayIndex)
End If
End FunctionFunction IsMissing(var)
IsMissing=((vartype(var) mod 8192 mod 10)=0)
End Function
这里,如果vartype(var) mod 8192(vbArray)不为vbError的话,则再对10(vbError)求模必不为0,因此var为无效参数,因为我们要求这里var定义为一维数组。
接下来,我们需要定义可变参数的函数:
Function myfuncVBS(arrVar)
Dim var1, var2
var1=Valid(arrVar,0)
var2=Valid(arrVar,1)
If IsMissing(var1) then
myfuncVBS="You have no pets."
ElseIf IsMissing(var2) then
myfuncVBS="Your dog has " & var1 & " puppies."
Else
myfuncVBS="Your dog has " & var1 & " puppies and your cat has " & var2 & " kittens."
End If
End Function
我们的自定义函数最多允许两个参数,但只声明一个数组参数(实际上只能从调用形式上才能看出来,记住,在VBScript中,数据的实际取值决定数据的类型。现在结合这个函数看,IsMissing和Valid辅助函数的语义就很直观了。在Valid函数调用下面的If …Else语句用来给缺省参数赋默认值。这些在C++中不用程序自己照料的事情,在这里必须得自己做了。
最后是如何调用这个允许变参的函数,答案是使用Array()函数。
wscript.echo myfuncVBS(Array(,1)) 'Option 1
wscript.echo myfuncVBS(Array(1)) 'Option 2
上面的代码中,如果不使用缺省参数,完整的调用形式应该为
Dim Value1
Dim Value2
wscript.echo myfuncVBS(Array(value1,value2)) 'No option
VBScript也没有名字空间的概念。似乎惟一的办法是将函数定义在类中,这样调用某个函数就转化为调用某个类的方法,而且必须使用对象做为前缀,可惜没有static关键字,所以调用之前仍然必须先构造对象。记得public和private关键字在声明函数和过程时可用。
Class MyNameSpaces_
Sub MyFunc()
wscript.echo "hello world!"
End Sub
End ClassSet MyNameSpaces = new MyNameSpaces_
MyNameSpaces.MyFunc
Set f = Nothing
好了,在讨论关于可变参数函数和名字空间的workaround之后,关于VBScript函数和过程讨论的也可以暂时告一段落了。当然,关于函数和过程名字的可见性仍然是一个很重要的话题,我将会在多文件工程中再次讨论它。