第5集丨IRIS 对象介绍

IRIS 对象类简介

InterSystems IRIS 通过以下对象类提供对象技术:%Library.RegisteredObject%Library.Persistent%Library.SerialObject
下图显示了这些类之间的继承关系,以及它们的一些参数和方法。类名称%Library包可以缩写,(例如)%Persistent %Library.Persistent 的缩写。此处,所有大写字母的项都是参数,以百分号开头的项是方法。
在这里插入图片描述
在典型的基于类的应用程序中,基于这些类(以及专用系统子类)定义类。所有对象都直接或间接地从这些类之一继承,并且每个对象都是以下类型之一:

  • 已注册的对象是 %RegisteredObject 的实例或子类。您可以创建这些对象,但不能保存它们。另外两个类继承自 %RegisteredObject,因此包括该类的所有参数、方法等。
  • 持久性对象是 %Persistent 的实例或子类。您可以创建、保存、打开和删除这些对象。
    持久性类会自动投影到可通过 Caché SQL 访问的表中。
  • 序列化对象是 %SerialObject对象的实例或子类。序列化类旨在用作另一个对象的属性。您可以创建和删除这些对象,但不能保存它们或独立于包含它们的对象打开它们。
    当包含在持久性对象中时,这些对象具有到 SQL 的自动投影

对象类的基本功能

使用对象类,您可以执行以下任务,其中包括:

  • 您可以创建一个对象(类的实例)。为此,请使用该类的 %New() 方法,该方法继承自 %RegisteredObject。例如:
set myobj=##class(Sample.Person).%New()
  • 您可以使用属性。
    您可以在任何类中定义属性,但它们仅在对象类中有用,因为只有这些类使您能够创建实例。
    任何属性都包含单个文本值、对象(可能是集合对象)或多维数组(罕见)。下面的示例演示对象值属性的定义:
Property Home As Sample.Address;
  • 如果类或其超类定义了实例方法,则可以调用该类的实例的方法。例如:
Method PrintPerson()
{
 Write !, "Name: ", ..Name
 Quit
}

如果 myobj 是定义此方法的类的实例,则可以按如下方式调用此方法:

Do myobj.PrintPerson()
  • 您可以验证属性值是否符合属性定义中给出的规则。

    • 所有对象都继承实例方法 %NormalizeObject(),该方法规范化对象的所有属性值。许多数据类型允许同一值的不同表示形式。规范化将值转换为其规范或规范化形式。%NormalizeObject() 根据此操作是否成功,返回 true 或 false。
    • 所有对象都继承实例方法 %ValidateObject(),该方法根据属性值是否符合属性定义返回 true 或 false。
    • 所有持久性对象都继承实例方法 %Save()。使用 %Save() 实例方法时,系统首先自动调用 %ValidateObject()
      相反,当您在例程级别工作并且不使用类时,您的代码必须包含逻辑来检查类型和其他输入要求。
  • 您可以定义回调方法,以便在创建、修改对象等时添加其他自定义行为。
    例如,若要创建类的实例,请调用该类的 %New()方法。如果该类定义了 %OnNew() 方法(回调方法),则 Caché 也会自动调用该方法。下面显示了一个简单的示例:

Method %OnNew() As %Status 
{
    Write "hi there"
    Quit $$$OK
}

在实际情况下,此回调可能会执行一些所需的初始化。它还可以通过写入文件或全局变量来执行日志记录。

OREFs

对象类的 %New() 方法创建一个内存中的内部结构来包含对象的数据,并返回指向该结构的 OREF(对象引用)。OREFCaché ObjectScript 中的一种特殊值。您应该记住以下几点:

  • 在终端中,当您显示 OREF 时,您会看到一个由数字组成的字符串,后跟一个 @ 符号,后跟类的名称。例如:
SAMPLES>set myobj=##class(Sample.Person).%New()
 
SAMPLES>w myobj
3@Sample.Person 
  • 如果不使用 OREF,则 Caché 会在需要 OREF 的情况下返回错误:<INVALID OREF>,能够识别此错误会很有帮助。这意味着该变量不是 OREF,但应该是 OREF
SAMPLES>set myobj.Name="Fred Parker"
 
SET myobj.Name="Fred Parker"
^
<INVALID OREF>
  • 创建 OREF 的方法只有一种:使用返回 OREF 的方法。返回 OREF 的方法在对象类或其子类中定义。
    以下内容不会创建 OREF,而是创建看起来像 OREF 的字符串:
SAMPLES>set testthis="4@Sample.Person"
  • 您可以通过编程方式确定变量是否包含 OREF。如果变量包含 OREF,则函数 $IsObject 返回 1 (true);否则,它将返回 0(假)。

流接口类

Caché 分配固定的空间量来保存字符串操作的结果。如果字符串表达式超过分配的空间量,则会产生<MAXSTRING>错误。除非启用长字符串,否则此限制为 32 KB,并且任何字符串属性都不能大于大约 32 KB。(其他任何属性也不能超过此限制,但其他限制会在长字符串限制应用之前生效)

如果需要传递长字符串值,或者需要属性来包含长字符串值,请使用流(stream)。是一个对象,可以包含其大小大于字符串大小限制的单个值。(在内部,Caché 创建并使用临时全局变量以避免内存限制)

您可以将流字段与 Caché SQL 一起使用,但有一些限制。

stream 类

主要的 Caché 流类使用由 %Stream.Object 类定义的公共流接口。通常使用流作为其他对象的属性,并保存这些对象。流数据可以存储在外部文件或 Caché 全局文件中,具体取决于您选择的类:

  • %Stream.FileCharacter %Stream.FileBinary 类用于写入外部文件的流
    (二进制流包含与 %Binary 类型相同类型的数据,并且可以保存大型二进制对象(如图片)。字符流包含与 %String 类型相同类型的数据,用于存储大量文本。
  • %Stream.GlobalCharacter%Stream.GlobalBinary 类用于存储在全局变量中的流
    若要使用流对象,请使用其方法。例如,使用这些类的 Write()方法将数据添加到流中,并使用 Read()从流中读取数据。流接口包括其他方法,如 Rewind()MoveTo()

例如,下面的代码创建一个全局字符流,并将一些数据写入其中:

 Set mystream=##class(%Stream.GlobalCharacter).%New()
 Do mystream.Write("here is some text to store in the stream ")
 Do mystream.Write("here is some more text")
 Write "this stream has this many characters: ",mystream.Size,!
 Write "this stream has the following contents: ",!
 Write mystream.Read()

集合类

当您需要一个容器来存储相关值集时,可以使用$LIST格式列表和多维数组,如本书前面所述。
如果您更喜欢使用类,Caché提供了列表类和数组类;这些称为集合

用作独立对象的列表和数组类

  • 若要创建列表对象,可以使用以下类:
    %Library.ListOfDataTypes — 定义文本值的列表。
    %Library.ListOfObjects — 定义对象列表(持久性或序列化)。
    若要操作列表对象,请使用其方法。例如:
Set Colors=##class(%Library.ListOfDataTypes).%New()
 Do Colors.Insert("Red")
 Do Colors.Insert("Green")
 Do Colors.Insert("Blue") 
 Write "Number of items in this list: ", Colors.Count()
 Write !, "Second item in the list: ", Colors.GetAt(2)
  • 同样,若要创建数组对象,可以使用以下类:
    %Library.ArrayOfDataTypes — 定义文本值的数组。每个数组项都有一个键和一个值。
    %Library.ArrayOfObjects — 定义对象数组(持久性或序列化)。每个数组项都有一个键和一个对象值。
    若要操作数组对象,请使用其方法。例如:
Set ItemArray=##class(%Library.ArrayOfDataTypes).%New()
 Do ItemArray.SetAt("example item","alpha")
 Do ItemArray.SetAt("another item","beta")
 Do ItemArray.SetAt("yet another item","gamma")
 Do ItemArray.SetAt("still another item","omega")
 Write "Number of items in this array: ", ItemArray.Count()
 Write !, "Item that has the key gamma: ", ItemArray.GetAt("gamma")

列表和数组作为属性

还可以将属性定义为列表或数组。

  • 若要将属性定义为列表,请使用以下格式:
Property MyProperty As list of Classname;

如果 Classname 是数据类型类,则Caché使用 %Collection.ListOfDT 提供的接口。如果 Classname 是一个对象类,则它使用 %Collection.ListOfObj 提供的接口。

  • 若要将属性定义为数组,请使用以下格式:
Property MyProperty As Array of Classname;

如果 Classname 是一个数据类型类,则 Caché 使用 %Collection.ArrayOfDT 提供的接口。如果 Classname 是一个对象类,则它使用%Collection.ArrayOfObj提供的接口。

实用的 Caché ObjectScript 方法

Caché ObjectScript 提供了以下函数,用于对象类:

$CLASSMETHOD

$CLASSMETHOD使您能够运行类方法,以类名和方法名的形式给出。例如:

SAMPLES>set class="Sample.Person"
 
SAMPLES>set obj=$CLASSMETHOD(class,"%OpenId",1)
 
SAMPLES>w obj.Name
Van De Griek,Charlotte M.

当您需要编写执行类方法的泛型代码,但类名(甚至方法名)事先不知道时,此函数很有用。例如:

 //read name of class from imported document
 Set class=$list(headerElement,1) 
 // create header object
 Set headerObj=$classmethod(class,"%New")

$METHOD

$METHOD 使您能够在给定实例和方法名称的情况下运行实例方法。例如:

SAMPLES>set obj=##class(Sample.Person).%OpenId(1)
 
SAMPLES>do $METHOD(obj,"PrintPerson")
 
Name: Van De Griek,Charlotte M.

$PROPERTY

$PROPERTY获取或设置给定实例的给定属性的值。例如:

SAMPLES>set obj=##class(Sample.Person).%OpenId(2)
 
SAMPLES>write $property(obj,"Name")
Edison,Patrick J.

$PARAMETER

$PARAMETER获取给定类参数的值(给定一个实例)。例如:

SAMPLES>set obj=##class(Sample.Person).%OpenId(2)
 
SAMPLES>write $parameter(obj,"EXTENTQUERYSPEC")
Name,SSN,Home.City,Home.State

$CLASSNAME

$CLASSNAME返回给定实例的类名。例如:

SAMPLES>set obj=##class(Sample.Person).%OpenId(1)
 
SAMPLES>write $CLASSNAME(obj)
Sample.Person

如果没有参数,此函数返回当前上下文的类名。这在实例方法中非常有用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值