目录
1.变量概述
- 在ObjectScript中,变量是在内存运行时,值的位置的名称,也就是说变量存在内存中。
- 必须使用set命令定义变量。大多数情况下,命令和函数在使用前都需要定义变量,如果变量未定义,则默认情况下,引用它会生成 <UNDEFINED>报错
//输出Error <UNDEFINED>
set x = y
- 变量可以不被指定类型,可以接收任何数值
2.变量类型
变量分为:局部变量、百分比变量、ProcedureBlock、进程私有全局变量、全局变量、数组变量、特殊变量
2.1 局部变量
- 局部变量是储存在当前Cache进程中的变量
- 只有创建它的Cache进程才能访问,该变量在进程终止时自动删除。
- 任何命名空间可以访问局部变量。
- 在方法中定义的局部变量只能在该方法中使用
- 在事务中,不会将局部变量set或kill视为日志记录的事务事件,即回滚事务时,对局部变量的操作不会被回滚,如下所示:
ClassMethod MyFunction()
{
set num = 1
//开启事务
ts
set num = 2
//回滚
tro
// 输出2
w num,!
}
- 局部变量名称限制为31个字符。可以指定长度超过31个字符的名称,但是只有前31位有效。
ClassMethod MyFunction3()
{
set abcabcdwewesssyygsoshbsdvv2233a = 1
set abcabcdwewesssyygsoshbsdvv2233ab = 3
// 输出3
w abcabcdwewesssyygsoshbsdvv2233a
// 输出3
w abcabcdwewesssyygsoshbsdvv2233ab
}
2.2 百分比变量
- 以%开头的变量称为百分比变量。
- 只有以%Z或者%z开头的变量才可用于应用程序代码,其他百分比变量保留给系统使用。
/// d ##class(Demo.Test).MyFunction1()
ClassMethod MyFunction1()
{
set %za = "a"
// 输出a
w %za
}
- 与局部变量不同的是,在方法中定义的局部变量只能在该方法中使用,而在方法中定义的百分比变量,可以在其他方法中使用,类似于全局变量效果
Class Demo.Test Extends %RegisteredObject
{
/// d ##class(Demo.Test).MyFunction1()
ClassMethod MyFunction1()
{
set num = 1
set %za = "a"
w %za,!
w num,!
}
/// d ##class(Demo.Test).MyFunction2()
ClassMethod MyFunction2()
{
w %za,!
w num,!
}
}
程序的运行结果如下所示:
DHC-APP>d ##class(Demo.Test).MyFunction2()
d ##class(Demo.Test).MyFunction2()
^
<SYNTAX>
DHC-APP>d ##class(Demo.Test).MyFunction1()
a
1
DHC-APP>d ##class(Demo.Test).MyFunction2()
a
w num,! }
^
<UNDEFINED>zMyFunction2+3^Demo.Test1.1 *num
- 通常复用一些固定配置的时候,会使用百分比变量
q:($data($zconfig))
set %zconfig = ##class(xx).xx()
2.3 ProcedureBlock(过程块)
- 私有变量。程序块中使用的任何变量都自动成为私有变量,并且只在该程序快中可见。
- 默认情况下,创建的所有对象方法都使用过程块(默认情况下创建的类,定义了类关键字ProcedureBlock),因此,默认情况下,在方法中创建的所有变量都是私有变量(方法互相之间不能访问),不能对私有变量使用new命令
- 手动添加Not ProcedureBlock后,局部变量作用域就会变成类似于全局变量效果,即各个方法中创建的变量可以互相访问和修改。
如下所示:默认情况下,创建的类中都是包含了ProcedureBlock
Class Demo.Test Extends %RegisteredObject
{
/// d ##class(Demo.Test).MyFunction1()
ClassMethod MyFunction1()
{
for i=1 : 1 : 5{
d ..MyFunction2()
}
}
ClassMethod MyFunction2()
{
set i = 2
w "i="_i_",this is a not procedureblock",!
}
}
执行命令d ##class(Demo.Test).MyFunction1(),打印结果如下:只打印5次:i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
由此可见,默认情况下,在方法中创建的所有变量都是私有变量(方法互相之间不能访问)。
如果给类定义了Not ProcedureBlock后,如下所示:
Class Demo.Test Extends %RegisteredObject [ Not ProcedureBlock ]
{
/// d ##class(Demo.Test).MyFunction1()
ClassMethod MyFunction1()
{
for i=1 : 1 : 5{
d ..MyFunction2()
}
}
ClassMethod MyFunction2()
{
set i = 2
//程序会陷入死循环,一直不停输出:i=2,this is a not procedureblock
w "i="_i_",this is a not procedureblock",!
}
}
调用d ##class(Demo.Test).MyFunction1(),会一直不停的打印:i=2,this is a not procedureblock,MyFunction2()中修改了MyFunction1()中变量i的值
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
i=2,this is a not procedureblock
......
2.4 进程私有全局变量
- 仅可由创建它的Cache进程访问,该变量在进程终止时会自动删除。定义进程私有全局变量如下所示:
set ^||num = 2
set ^||name = "Jack"
- 任何命名空间都可以访问该变量
ClassMethod MyFunction2()
{
kill ^||num
set ^||num = 2
//输出^||num = 2
zw ^||num
//输出2
w ^||num
//切换命名空间
set $namespace = "DHC-APP"
//输出^||num = 2
zw ^||num
//输出2
w ^||num
}
- 各个方法之间可以访问进程私有全局变量
/// d ##class(Demo.Test).MyFunction6()
ClassMethod MyFunction6()
{
set ^||num = 1
d ..MyFunction7()
}
ClassMethod MyFunction7()
{
//输出1
w ^||num
}
- 进程私有全局变量对于临时储存大数据值特别有用
- 回滚事务时,对进程私有全局变量这些没有任何影响,即回滚事务时,对进程私有全局变量操作不会被回滚
ClassMethod MyFunction()
{
set ^||num = 1
//开启事务
ts
set ^||num = 2
//回滚
tro
w ^||num,!
}
- 名称限制为31个字符。可以指定长度超过31个字符的名称,但是只有前31位有效。
ClassMethod MyFunction3()
{
set ^||abcabcdwewesssyygsoshbsdvv2233a = 1
set ^||abcabcdwewesssyygsoshbsdvv2233ab = 3
// 输出3
w ^||abcabcdwewesssyygsoshbsdvv2233a
// 输出3
w ^||abcabcdwewesssyygsoshbsdvv2233ab
}
2.5 使用^GETPPGINFO
- 使用^GETPPGINFO可以以块为单位,显示当前进程私有全局变量及其控件分配。会列出进程私有全局变量的下标或值。
- 可以通过指定进程ID(PID)来显示特定进程私有全局变量;也可以通过指定“*”字符串通配符来显示所有进程的进程私有全局变量
- 必须在%SYS命名空间才能调用^GETPPGINFO
2.6 全局变量(Global)
- 自动储存在Cache数据库中的永久变量。局部变量和进程私有全局变量都是写入内存中,全局变量是写入磁盘中。定义全局变量如下:
ClassMethod MyFunction4()
{
//定义局部变量
set myLocal = "这是局部变量"
//定义全局变量
set ^myGlobal = "这是存储在当前命名空间的全局变量"
//输出^myGlobal="这是存储在当前命名空间的全局变量"
zw ^myGlobal
}
- 全局变量(Global)是一个B+树
- 任何进程可以访问全局变量,并且在创建它的进程终止后持续存在,直到被删除。
- 全局变量被映射到特定的命名空间,并且只有创建该全局变量的命名空间才能访问,如果其他命名空间需要访问,则需要使用扩展引用。
- 将全局变量的设置或终止视为日志记录的事务事件,即回滚事务时,将撤销这些操作。
ClassMethod MyFunction9()
{
set ^myGlobal = 1
ts
set ^myGlobal = 2
tro
//输出^myGlobal=1
zw ^myGlobal
}
- 同样的,名称限制为31个字符。可以指定长度超过31个字符的名称,但是只有前31位有效。
ClassMethod MyFunction10()
{
set ^abcabcdwewesssyygsoshbsdvv2233a = 1
set ^abcabcdwewesssyygsoshbsdvv2233ab = 2
//输出^abcabcdwewesssyygsoshbsdvv2233a=2
zw ^abcabcdwewesssyygsoshbsdvv2233a
//输出^abcabcdwewesssyygsoshbsdvv2233a=2
zw ^abcabcdwewesssyygsoshbsdvv2233ab
}
- 可以使用$ZREFERENCE来确定最近使用的全局变量名称;$QSUBSCRIPT返回指定全局变量节点的名称;$QLENGTH返回下标的数量
- 对于当前进程,局部变量名必须是唯一的,其他进程可以具有同名的局部变量。进程全局变量或全局变量可以与局部变量、百分比变量同名。如下所示: xy、%xy、^||xy和^xy是四个不同的变量
ClassMethod MyFunction11()
{
//定义局部变量
set xy = 1
//定义百分比变量
set %xy = 2
//定义进程私有全局变量
set ^||xy = 3
//定义全局变量
set ^xy = 4
//输出xy=1
zw xy
//输出%xy=2
zw %xy
//输出^||xy=3
zw ^||xy
//输出^xy=4
zw ^xy
}
- 推荐变量使用的顺序
局部变量(效率最高)、进程全局变量、全局变量。百分比变量看情况使用
2.7 数组变量与下标变量
- 局部变量、进程私有变量和全局变量都可以采用下标
- 下标名称的最大长度为511个编码字节,超过最大下标长度将会报错;允许的最长整数为309位,超过此限制将会导致<MAXNUMBER>错误,因此,必须将长度超过309个字符的数字下标指定为字符串。
- 局部变量的最大下标级别数为255,;全局变量或进程私有全局变量的最大下标级别数位253.超过最大下标级别数会导致错误
//级别数为3
set ^||xy("a","b","c") = 2
- 下标为数字的为数组变量,下标不为数字的为下标变量。下标变量包含数组变量。
//数组变量
set ^x(1) = 1
//下标变量
set ^x("a") = 2
//下标变量
set color("red") = "red"
2.8 特殊变量(也称为系统变量)
- 一组特殊的内置变量,其中包含Cache操作环境的特定方面的值,Cache定义了所有特殊变量;Cache将所有特殊变量设置为初始值(有时为空字符串值),一些特殊变量可以由用户设置,其他变量只能由Cache设置。特殊变量不是数组变量。
ClassMethod MyFunction12()
{
//输出66330,71864
w $Horolog,!
/*
输出版本号:Cache for Windows (x86-64) 2016.2
(Build 736_0_16871U) Wed Dec 21 2016 09:38:49 EST
*/
w $zversion
}
2.9 对象属性
与对象的特定实例相关联并存储在其中的值
Class Demo.First Extends %RegisteredObject
{
/// 声明属性
Property name As %String;
/// d ##class(Demo.First).Variable()
ClassMethod Variable()
{
/// 初始化一个对象
set obj = ..%New()
/// 设置属性值
set obj.name = "Jack"
//输出Jack
w obj.name
}
}
3.变量类型和转换
如下所示:
from | to | 规则 |
Number | String | 使用表示数字值的字符串,例如“2.6” |
String | Number | 字符串的前导字符串被解释为数字文字,例如"-6.21abs34"被解释为-6.21,而"ab2sc22"被解释为0 |
Object | Number | 使用给定对象引用的内部对象实例编号,该值为整数 |
Object | String | 使用n@cls形式得字符串,其中n是内部对象实例编号,cls是给定对象的类名
|
Number | Object | 不允许 |
String | Object | 不允许 |