IRIS 对象类简介
InterSystems IRIS
通过以下对象类提供对象技术:%Library.RegisteredObject
、%Library.Persistent
和 %Library.SerialObject
。
下图显示了这些类之间的继承关系,以及它们的一些参数和方法。类名称%Library包可以缩写,(例如)%Persistent
是 %Library.Persistent
的缩写。此处,所有大写字母的项都是参数,以百分号开头的项是方法。
在典型的基于类的应用程序中,基于这些类(以及专用系统子类)定义类。所有对象都直接或间接地从这些类之一继承,并且每个对象都是以下类型之一:
%RegisteredObject
的实例或子类。您可以创建这些对象,但不能保存它们。另外两个类继承自 %RegisteredObject
,因此包括该类的所有参数、方法等。%Persistent
的实例或子类。您可以创建、保存、打开和删除这些对象。%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
(对象引用)。OREF
是 Caché ObjectScript
中的一种特殊值。您应该记住以下几点:
OREF
时,您会看到一个由数字组成的字符串,后跟一个 @
符号,后跟类的名称。例如:SAMPLES>set myobj=##class(Sample.Person).%New()
SAMPLES>w myobj
3@Sample.Person
OREF
,则 Caché
会在需要 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é
分配固定的空间量来保存字符串操作的结果。如果字符串表达式超过分配的空间量,则会产生
错误。除非启用长字符串
,否则此限制为 32 KB
,并且任何字符串属性都不能大于大约 32 KB。(其他任何属性也不能超过此限制,但其他限制会在长字符串限制应用之前生效)
如果需要传递长字符串值,或者需要属性来包含长字符串值,请使用流(stream
)。流
是一个对象,可以包含其大小大于字符串大小限制的单个值。(在内部,Caché
创建并使用临时全局变量以避免内存限制)
您可以将流字段与 Caché SQL 一起使用,但有一些限制。
主要的 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
使您能够运行类方法,以类名和方法名的形式给出。例如:
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
使您能够在给定实例和方法名称的情况下运行实例方法。例如:
SAMPLES>set obj=##class(Sample.Person).%OpenId(1)
SAMPLES>do $METHOD(obj,"PrintPerson")
Name: Van De Griek,Charlotte M.
$PROPERTY
获取或设置给定实例的给定属性的值。例如:
SAMPLES>set obj=##class(Sample.Person).%OpenId(2)
SAMPLES>write $property(obj,"Name")
Edison,Patrick J.
$PARAMETER获取给定类参数的值(给定一个实例)。例如:
SAMPLES>set obj=##class(Sample.Person).%OpenId(2)
SAMPLES>write $parameter(obj,"EXTENTQUERYSPEC")
Name,SSN,Home.City,Home.State
$CLASSNAME
返回给定实例的类名。例如:
SAMPLES>set obj=##class(Sample.Person).%OpenId(1)
SAMPLES>write $CLASSNAME(obj)
Sample.Person
如果没有参数,此函数返回当前上下文的类名。这在实例方法中非常有用。