CachéObjectScript
包含特定于处理类和对象的功能。这些是:
相对点语法(..
)—— 用于访问当前对象的属性或调用当前对象的方法。
##class
语法 —— 用于调用类方法,将对象引用强制转换为另一个类以调用方法,或访问类参数的值。
$this
语法 —— 用于获取当前实例的OREF的句柄,例如将其传递给另一个类或另一个引用当前实例的属性或方法的类。
##super
语法 —— 用于从子类方法中调用超类方法。
动态访问对象 —— 用于调用类方法和实例方法,以及用于引用对象属性。
i%
语法 —— 用于从实例变量自身的Get或Set访问器方法中引用实例变量,或绕过其Get或Set方法。
..#
语法 —— 用于在同一类的方法中引用类参数的值。
相对点语法 (…) 提供了一种在当前上下文中引用方法或属性的机制。
例如,假设有一个 %Integer
类型的 Bricks
属性:
Property Bricks As %Integer;
然后,CountBricks()
方法可以引用具有相对点语法的 Bricks:
Method CountBricks()
{
Write "There are ",..Bricks," bricks.",!
}
同样,WallCheck()
方法可以引用 CountBricks()
和 Bricks
:
Method WallCheck()
{
Do ..CountBricks()
If ..Bricks < 100 {
Write "Your wall will be small."
}
}
##class
语法允许您:
注意:##class 不区分大小写。
若要调用类方法,语法为以下任一语法:
>Do ##class(Package.Class).Method(Args)
>Set localname = ##class(Package.Class).Method(Args)
##class
作为表达式的一部分也是有效的,如: Write ##class(Class).Method(args)*2
>Set LocalInstance = ##class(Package.Class).%New()
若要将一个类的方法转换为另一个类的方法,语法为以下任一方法:
>Do ##class(Package.Class1)Class2Instance.Method(Args)
>Set localname = ##class(Package.Class1)Class2Instance.Method(Args)
可以强制转换类方法和实例方法。
例如,假设两个类,MyClass.Up
和MyClass.Down
,两者都有 Go()
方法。对于 MyClass.Up
,此方法如下:
Method Go()
{
Write "Go up.",!
}
对于 MyClass.Down
,Go()
方法如下:
Method Go()
{
Write "Go down.",!
}
然后,您可以创建MyClass.Up
的实例,并使用它来调用 MyClass.Down.Go
方法:
>Set LocalInstance = ##class(MyClass.Up).%New()
>Do ##class(MyClass.Down)LocalInstance.Go()
Go down.
引用其他方法的更通用方法是 $METHOD
和 $CLASSMETHOD
函数,它们分别是 instance
和 class
方法;它们提供了一种以编程方式引用包、类和方法的机制。
若要访问类参数,可以使用以下表达式:
##class(Package.Class).#PARMNAME
其中 Package.Class
是类的名称,PARMNAME
是参数的名称。例如:
w ##class(%XML.Adaptor).#XMLIGNOREINVALIDTAG
还可以使用$PARAMETER
函数
$this
变量提供当前实例的 OREF
句柄,例如,用于将其传递给另一个类或另一个类以引用当前实例的属性或方法。当实例引用其自己的属性或方法时,相对点语法更快,因此是首选。
注意:$this
不区分大小写;因此,$this
、$This
、$THIS
或任何其他变体都具有相同的值。
Method CalcTax() As %Numeric
{
Set TaxRate = ##class(Accounting.Utils).GetTaxRate($this)
Write "The tax rate for ",..City,", ",..State," is ",TaxRate*100,"%",!
Set TaxableSubtotal = ##class(Accounting.Utils).GetTaxableSubTotal($this)
Write "The taxable subtotal for this order is $",TaxableSubtotal,!
Set Tax = TaxableSubtotal * TaxRate
Write "The tax for this order is $",Tax,!
}
假设子类方法重写超类方法。在子类方法中,可以使用 ##super()
语法来调用被覆盖的超类方法。
注意:##super
不区分大小写。
MyClass.Down
ClassMethod Simple()
{
Write "Superclass.",!
}
MyClass.Down.Simple
ClassMethod Simple()
{
Write "Subclass.",!
Do ##super()
}
则子类方法 MyClass.Down.Simple()
的输出为:
>Do ##Class(MyClass.Down).Simple()
Subclass.
Superclass.
##super
仅影响当前方法调用。如果该方法进行任何其他调用,则这些调用是相对于当前对象或类的,而不是相对于超类的
MyClass.Up
Class MyClass.Up Extends %Persistent
{
ClassMethod CallMyName()
{
Do ..MyName()
}
ClassMethod MyName()
{
Write "Called from MyClass.Up",!
}
}
MyClass.Down
Class MyClass.Down Extends MyClass.Up
{
ClassMethod CallMyName()
{
Do ##super()
}
ClassMethod MyName()
{
Write "Called from MyClass.Down",!
}
}
然后调用 CallMyName()
方法会产生以下结果:
USER>d ##class(MyClass.Up).CallMyName()
Called from MyClass.Up
USER>d ##class(MyClass.Down).CallMyName()
Called from MyClass.Down
##super
也适用于接受参数的方法。如果子类方法未指定参数的默认值,请确保该方法通过引用超类来传递参数。
例如,假设超类 (MyClass.Up.SelfAdd()
) 中方法的代码为:
ClassMethod SelfAdd(Arg As %Integer)
{
Write Arg,!
Write Arg + Arg
}
子类 (MyClass.Down.SelfAdd()
) 中的方法使用 ##super
并通过引用传递参数:
ClassMethod SelfAdd(Arg1 As %Integer)
{
Do ##super(.Arg1)
Write !
Write Arg1 + Arg1 + Arg1
}
则其输出为:
>Do ##Class(MyClass.Down).SelfAdd(2)
2
4
6
>
在 MyClass.Down.SelfAdd()
中,注意参数名称前的句点
。如果我们省略了这一点,并且在没有提供参数的情况下调用该方法,我们将收到一个
错误。
Caché
提供了多个支持对象通用处理的函数。它们通过允许在运行时计算对类及其方法或属性之一的引用来实现此目的。(这在 Java 中称为反射。这些功能包括:
$CLASSNAME
— 返回类的名称。$CLASSMETHOD
— 支持对类方法的调用。$METHOD
— 支持对实例方法的调用。$PARAMETER
— 返回指定类的类参数的值。$PROPERTY
— 支持对实例特定属性的引用。函数名称在此处以全部大写字母显示,但实际上它们不区分大小写。
返回类的名称。此函数返回类的名称。签名是:
$CLASSNAME(Instance)
其中 Instance
是 OREF
。
s person = ##class(NA.Object.Person).%New()
q $CLASSNAME(person)
此函数在指定的类中执行命名类方法。签名是:
$CLASSMETHOD (Classname, Methodname, Arg1, Arg2, Arg3, ... )
此函数为指定类的指定实例执行命名实例方法。签名是:
$METHOD (Instance, Methodname, Arg1, Arg2, Arg3, ... )
此函数返回指定类的类参数的值。签名是:
$PARAMETER(Instance,Parameter)
此函数获取或设置指定类的实例中的属性值。如果属性是多维的,则属性名称后面的以下参数将用作访问属性值的索引。签名是:
$PROPERTY (Instance, PropertyName, Index1, Index2, Index3... )
创建任何类的实例时,系统都会为该类的每个非计算属性创建一个实例变量。实例变量保存属性的值。对于属性 PropName
,实例变量命名为 i%PropName
,并且此变量名称区分大小写。这些变量在类的任何实例方法中都可用。
例如,如果某个类具有属性 Name
和 DOB
,则实例变量 i%Name
和 i%DOB
在该类的任何实例方法中都可用。
在内部,Caché
还使用名称为 r%PropName
和 m%PropName
的其他实例变量,但不支持直接使用这些变量。
实例变量分配了进程专用的内存中存储。请注意,这些变量不保存在局部变量符号表中,并且不受 Kill
命令的影响。
#
语法允许从同一类的方法中引用类参数。
例如,如果类定义包含以下参数和方法:
Parameter MyParam = 22;
ClassMethod WriteMyParam()
{
Write ..#MyParam
}