• 第5集丨Caché 对象介绍


    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()
    
    • 1
    • 您可以使用属性。
      您可以在任何类中定义属性,但它们仅在对象类中有用,因为只有这些类使您能够创建实例。
      任何属性都包含单个文本值、对象(可能是集合对象)或多维数组(罕见)。下面的示例演示对象值属性的定义:
    Property Home As Sample.Address;
    
    • 1
    • 如果类或其超类定义了实例方法,则可以调用该类的实例的方法。例如:
    Method PrintPerson()
    {
     Write !, "Name: ", ..Name
     Quit
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

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

    Method %OnNew() As %Status 
    {
        Write "hi there"
        Quit $$$OK
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    OREFs

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

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

    流接口类

    Caché 分配固定的空间量来保存字符串操作的结果。如果字符串表达式超过分配的空间量,则会产生错误。除非启用长字符串,否则此限制为 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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    集合类

    当您需要一个容器来存储相关值集时,可以使用$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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 同样,若要创建数组对象,可以使用以下类:
      %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")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    列表和数组作为属性

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

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

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

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

    如果 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.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

    $METHOD

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

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

    $PROPERTY

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

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

    $PARAMETER

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

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

    $CLASSNAME

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

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

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

  • 相关阅读:
    【无标题】
    大语言模型Ollama
    文心一言 VS 讯飞星火 VS chatgpt (244)-- 算法导论18.1 2题
    使用Lightrun对Java应用程序进行性能调整
    mybatis config 配置
    2024海康威视校招面试真题汇总及其解答(一)
    软件设计模式
    下载和补全ComfyUI节点方法之一
    动态IP代理是什么?一文看懂动态代理IP
    大学解惑08 - 做一个简单的先注册再登录功能
  • 原文地址:https://blog.csdn.net/DUQGQG/article/details/125865864