Caché Objects | 第三章 | 特定于对象的 ObjectScript 功能

目录

  • 一、相对点语法 (..)
  • 二、##Class 语法
    • 2.1 调用类方法
    • 2.2 强制转换方法
    • 2.3 访问类参数
  • 三、$this 语法
  • 四、##super 语法
    • 4.1 基本使用
    • 4.2 super 影响的调用
    • 4.3 ##super 和方法参数
  • 五、动态访问对象
    • 5.1 $CLASSNAME
    • 5.2 $CLASSMETHOD
    • 5.3 $METHOD
    • 5.4 $PARAMETER
    • 5.5 $PROPERTY
  • 六、i% 语法
  • 七、..# 语法

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 语法允许您:

  • 执行类方法(相当于静态方法,无需实例)
  • 将一个类中的方法转换为另一个类中的方法。
  • 访问类参数

注意:##class 不区分大小写。

2.1 调用类方法

若要调用类方法,语法为以下任一语法:

>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()

2.2 强制转换方法

若要将一个类的方法转换为另一个类的方法,语法为以下任一方法:

>Do ##class(Package.Class1)Class2Instance.Method(Args)
>Set localname = ##class(Package.Class1)Class2Instance.Method(Args)

可以强制转换类方法和实例方法。

例如,假设两个类,MyClass.UpMyClass.Down,两者都有 Go() 方法。对于 MyClass.Up,此方法如下:

Method Go()
{
    Write "Go up.",!
}

对于 MyClass.DownGo() 方法如下:

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 函数,它们分别是 instanceclass 方法;它们提供了一种以编程方式引用包、类和方法的机制。

2.3 访问类参数

若要访问类参数,可以使用以下表达式:

##class(Package.Class).#PARMNAME

其中 Package.Class 是类的名称,PARMNAME 是参数的名称。例如:

w ##class(%XML.Adaptor).#XMLIGNOREINVALIDTAG

还可以使用$PARAMETER函数

三、$this 语法

$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() 语法来调用被覆盖的超类方法。

注意##super 不区分大小写。

4.1 基本使用

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.

4.2 super 影响的调用

##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

4.3 ##super 和方法参数

##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 — 支持对实例特定属性的引用。

函数名称在此处以全部大写字母显示,但实际上它们不区分大小写

5.1 $CLASSNAME

返回类的名称。此函数返回类的名称。签名是:

$CLASSNAME(Instance)

其中 InstanceOREF

s person = ##class(NA.Object.Person).%New()
q $CLASSNAME(person)

5.2 $CLASSMETHOD

此函数在指定的类中执行命名类方法。签名是:

$CLASSMETHOD (Classname, Methodname, Arg1, Arg2, Arg3, ... )

5.3 $METHOD

此函数为指定类的指定实例执行命名实例方法。签名是:

$METHOD (Instance, Methodname, Arg1, Arg2, Arg3, ... )

5.4 $PARAMETER

此函数返回指定类的类参数的值。签名是:

$PARAMETER(Instance,Parameter)

5.5 $PROPERTY

此函数获取或设置指定类的实例中的属性值。如果属性是多维的,则属性名称后面的以下参数将用作访问属性值的索引。签名是:

$PROPERTY (Instance, PropertyName, Index1, Index2, Index3... )

六、i% 语法

创建任何类的实例时,系统都会为该类的每个非计算属性创建一个实例变量。实例变量保存属性的值。对于属性 PropName,实例变量命名为 i%PropName,并且此变量名称区分大小写。这些变量在类的任何实例方法中都可用

例如,如果某个类具有属性 NameDOB,则实例变量 i%Namei%DOB 在该类的任何实例方法中都可用。

在内部,Caché 还使用名称为 r%PropNamem%PropName 的其他实例变量,但不支持直接使用这些变量。

实例变量分配了进程专用的内存中存储。请注意,这些变量不保存在局部变量符号表中,并且不受 Kill 命令的影响。

七、…# 语法

# 语法允许从同一类的方法中引用类参数。
例如,如果类定义包含以下参数和方法:

Parameter MyParam = 22;

ClassMethod WriteMyParam()
{
    Write ..#MyParam
}

你可能感兴趣的:(Caché,Objects,Caché,Caché,Objects)