第二章 Caché 定义和编译类

第二章 定义和编译类

介绍术语

如下展示Caché类定义,和一些典型元素

示例如下:

Class Demo.MyClass Extends %RegisteredObject
{

Property Property1 As %String;

Property Property2 As %Numeric;

Method MyMethod() As %String
{
   set returnvalue=..Property1_..Property2
   quit returnvalue
}

}

如下几个重点:

  • 类全名:Demo.MyClass,包名:Demo,简类名:MyClass
  • Demo.MyClass 类扩展了类 %RegisteredObject,等同于,Demo.MyClass继承%RegisteredObject,%RegisteredObject是父类,或Demo.MyClass是%RegisteredObject的子类,一个类可以有多个父类。子类可以用调用父类的方法。
  • Demo.MyClass定义了两个属性:Property1 和 Property2,Property1的属性是 %String(字符串)类型,Property2的属性是%Numeric(数字)类型
  • Demo.MyClass定义了一个方法:MyMethod()返回类型是 %String。

Demo.MyClass 涉及了一些Caché系统类。这个类是 %RegisteredObject(全名是 %Library.RegisteredObject) %String (%Library.String), 和 %Numeric (%Library.Numeric). %RegisteredObject 是Caché的关键类,因为它定义了对象接口,它提供了创建对象的实例, %String 和 %Numeric 数据类型类。因此,对应的属性有对应的值(不包含其他类型的值)。

类的类型

Caché提供了大量类定义,可以从如下方式使用:

  • 可以使用Caché的类作为父类
  • 可以使用Caché类作为属性值、方法的参数值、方法返回的值,等等。
  • 一些Caché类提供了一些特殊的API,通常不会以上述任何一种方式使用这些类。而是编写调用API方法的代码。

父类最常见的选择如下:

  • %RegisteredObject 这个以最通用的形式表示对象接口
  • %Persistent 这个类表示一个持久对象。除了提供对象接口之外,该类还提供了将对象保存到数据库和从数据库读取对象的方法。
  • %SerialObject 这个类表示可以嵌入(序列化在)另一个对象中的对象。
  • 这几个类可以是任何类的父类
  • None - 创建类时不必指定父类

对于属性值、方法的参数值、方法返回的值等最常见的选择如下:

  • 对象类
  • 数据类型类
  • 集合类
  • 流类

对象类

对象类指的是 %RegisteredObject 的子类,使用对象类,可以创建类的实例、指定实例的属性和调用实例的方法。

通用术语“对象”指的是对象类的实例。
对象类一般分为三类:

  • 对是对象 和 注册类 是%RegisteredObject 的子类
    而不是%Persistent或%SerialObject的子类
  • 持久类是%Persistent的子类,%Persistent是%RegisteredObject的子类。%Persistent类包括%RegisteredObject的行为方法,并增加了将对象保存到磁盘、重新打开它们等功能
  • 序列化类是%SerialObject的子类,它是%RegisteredObject的子类。%SerialObject类包括%RegisteredObject的行为方法,并增加了创建表示对象状态的字符串的能力,以便将其包含为另一个对象(通常是临时对象或持久对象)中的属性。短语序列化一个对象指的是这个字符串的创建。

下图显示了这三个类之间的继承关系。方框中列出了类中定义的一些方法:
在这里插入图片描述

  • 集合类和流类是具有特定行为的对象类。

数据类型类

数据类型类指的是ClassType关键字等于数据类型或此类的任意子类。这些类不是对象类(数据类型类不能定义属性,也不能创建类的实例)。数据类型类(更准确地说是数据类型生成器类)的用途是用作对象类的属性类型

类成员

Caché类定义可以包括以下项目,都称为类成员:

  • Parameters 参数定义一个常数值供该类使用。在大多数情况下,该值是在编译时设置的。
  • Methods 支持两种类型的方法:
  1. 实例方法和类方法。从类的特定实例调用实例方法并执行与该实例相关的操作;这种类型的方法只在对象类中有用。
  2. 类方法是无论其类的实例是否在内存中都可以调用的方法;这种类型的方法在其他语言中称为静态方法。
  • Properties 属性包含类实例的数据,属性只在对象类中有用。
  • Class queries 类查询定义一个可由类使用的SQL查询,并指定一个类作为查询的容器,通常(但不一定)要在持久类中定义类查询,以便对该类存储的数据执行查询。但是,可以在任何类中定义类查询。
  • 其他类型的类成员只与持久类相关:
  1. Storage definitions 存储定义
  2. Indices 索引
  3. Foreign keys 外键
  4. SQL triggers sql触发器
  • XData blocks XData块是类中啊规则格式的XML文档,通常由类中的方法使用。XData有许多可能的应用。
  • Projections 类映射提供了扩展类编译器行为的方法。

映射机制由Java和c++映射使用;这就是映射一词的由来。

类型的属性

在形式上,有两种属性:属性和关系。

属性值Attribute和properties通常简称为属性。根据属性定义,它持有的值可以是以下任意一个:

  • 文本值,如“MyString”和1。保存文字值的属性基于数据类型类,也称为数据类型属性。
  • 流。流是一Caché对象,它包含的值对于字符串来说太长了。
  • 集合。Caché提供了将属性定义为列表或数组的能力。列表或数组项可以是文字值,也可以是对象。
  • 其他属性。
  • 关系包含对象之间的关联。关系属性被称为关系。关系仅在持久类中受支持。

定义类:基础

通常,使用Studio来定义类。还可以使用Caché类定义类或通过XML类定义文件以编程方式定义类。如果使用SQL DDL语句定义一个SQL表,那么Caché将创建一个对应的类定义。

选择一个父类

当定义一个类时,你可以选择一个或多个类作为父类,如果只有一个父类,那么在类定义时 Extends 关键字后面跟着父类

Class Demo.MyClass Extends Superclass 
{

//...

}

如果有多个超类,请将它们指定为逗号分隔的列表,用圆括号括起来

Class Demo.MyClass Extends (Superclass1, Superclass2, Superclass3) 
{

//...

}

创建类时不需要指定父类。使用%RegisteredObject作为父类是很常见的,即使该类不表示任何类型的对象,因为这样做使类可以访问许多常用的宏,可以直接使用它们的包含文件。

包含文件

创建类不继承%RegisteredObject或其任何子类的类时,包含以下包含文件:

  • %occStatus.inc,定义了使用%Status值的宏。
  • %occMessages.inc,定义了处理消息的宏。

如果类继承了%RegisteredObject或它的任何子类,则可以自动使用这些宏。

还可以创建自己的包含文件,并根据需要将它们包含在类定义中。

若要在类定义的开头包含包含文件,请使用以下形式的语法。注意,必须忽略包含文件的.inc扩展名:

Include MyMacros

例如:

Include %occInclude

Class Classname 
{
}

要在类定义的开头包含多个include文件,请使用以下形式的语法:

Include (MyMacros, YourMacros) 

注意这个语法没有#号 。而且,Include指令不区分大小写,因此可以使用Include。包含文件名是大小写敏感的。

指定类的关键词

在某些情况下,有必要控制类编译器生成的代码的细节.例如,对于持久类,如果不想(或不能)使用默认表名,可以指定SQL表名.再如说,final 类不能创建它的子类,类定义支持一组特定的关键字。如果需要指定类关键字,请在父类后面的方括号中包含它们,如下所示:

Class Demo.MyClass Extends Demo.MySuperclass [ Keyword1, Keyword2, ...]
{

//...

}

例如,可用的类关键字包括Abstract和Final。

定义类参数的介绍

类参数为给定类的所有对象定义一个常数值。要在类定义中添加类参数,请在类中添加如下元素之一:

Parameter PARAMNAME as Type;
Parameter PARAMNAME as Type = value;
Parameter PARAMNAME as Type [ Keywords ] = value;

关键字表示任何参数关键字。

定义属性介绍

对象类可以包含属性。

要在类定义中添加属性,请在类中添加以下元素之一:

Property PropName as Classname;
Property PropName as Classname [ Keywords ] ;
Property PropName as Classname(PARAM1=value,PARAM2=value) [ Keywords ] ;
Property PropName as Classname(PARAM1=value,PARAM2=value) ;
  • PropName是属性的名称。

  • Classname是一个可选的类名(如果省略这个,则默认类型为%String)。

  • 关键字表示任何属性关键字。

  • 根据属性使用的类,还可以指定属性参数,如第三和第四种变体所示。

注意,如果包含属性参数,则将其括在圆括号中,并放在任何属性关键字之前。还要注意,如果包含属性关键字,则用方括号括起来。

定义方法简介

可以在Caché类中定义两种方法:类方法和实例方法。

要在类定义中添加类方法,请在类中添加如下元素:

ClassMethod MethodName(arguments) as Classname [ Keywords]
{
//method implementation
}
  • MethodName是方法的名称。
  • arguments是一个逗号分隔的参数列表。
  • Classname是一个可选的类名,表示该方法返回的值的类型(如果有)。如果方法不返回值,则省略As Classname部分。
  • Keywords表示任何方法关键字。这些是可选的。
    要添加实例方法,请使用与方法相同的语法,而不是使用ClassMethod:
Method MethodName(arguments) as Classname [ Keywords]
{
//method implementation
}

命名约定

类和类成员遵循特定的命名约定。这些将在本节中详细介绍。

类和类成员名称的规则

本节描述类名和成员名的规则,如最大长度、允许的字符等。完整的类名包括它的包名,如下一节所述。

每个标识符在其上下文中必须是唯一的(也就是说,没有两个类可以有相同的名称)。Caché对包名、类名和成员名有以下限制:

  • 每个包名最多可以有189个字符。
  • 每个类名最多可以有60个字符。
  • 每个方法和属性名最多可以有180个字符。
  • 属性名称和属性上的任何索引的组合长度应不超过180个字符。
  • 每个成员的全名(包括不合格的成员名、类名、包名和任何分隔符)必须是220个字符或更少。
  • 每个名称都可以包含Unicode字符。

标识保护的例子:必须与名称的大小写完全匹配,同时,两个类不能具不同的名称在一个例子里。例如,出于唯一性的目的,标识符“ID1”和“id1”被认为是相同的。

标识符必须以字母字符开头,尽管它们可能在第一个位置之后包含数字字符。标识符不能包含空格或标点符号,包名除外,包名可能包含"."。在Unicode系统中,标识符可能包含Unicode字符。

某些标识符以“%”字符开头;这标识了一个系统项。例如,Caché库提供的许多方法和包都以“%”字符开头。

可以对成员名进行分隔,这允许它们包含不允许的字符。若要创建带分隔符的成员名称,请对名称的第一个和最后一个字符使用双引号。例如:

Property "My Property" As %String;

类名

每个类都有一个唯一标识它的名称。一个完整的类名由两部分组成:一个包名和类名,类名跟在最后一个点“.”后面。类名在其包内必须是唯一的;包名在Caché命名空间中必须是唯一的。

因为持久化类被自动映射为SQL表,类必须指定表名不能用SQL 保留字;如果持久性类的名称是一个SQL保留字,那么类定义还必须为其SQLTableName关键字指定一个有效的非保留字值。

类成员名字

每个类成员(如属性或方法)的名称必须在其类中是唯一的,并且最大长度为180个字符。此外,持久性的成员不能使用SQL保留字作为其标识符。但是,它可以使用该成员的SQLName或SQLFieldName关键字(视情况而定)定义别名。

注意:InterSystems强烈建议不要给两个成员相同的名称。这可能会产生意想不到的结果。

继承

Caché类可以从已经存在的类继承。如果一个类从另一个类继承,继承类被称为子类,而它派生的一个或多个类被称为父类。

下面是一个使用两个父超类的类定义示例

Class User.MySubclass Extends (%Library.Persistent, %Library.Populate)
{
}

注意:这里显示的语法对应于Super关键字,它在Studio Inspector和导出为XML的类定义中可见。

除了从父类继承方法外,属性还从系统属性行为类继承其他方法,对于数据类型属性,则从数据类型类继承。

例如,如果有一个类定义为Person:

Class MyApp.Person Extends %Library.Persistent
{
Property Name As %String;
Property DOB As %Date;
}

从它派生一个新类Employee很简单:

Class MyApp.Employee Extends Person
{
Property Salary As %Integer;
Property Department As %String;
}

这个定义将Employee类建立为Person类的子类。除了自己的类参数、属性和方法之外,Employee类还包含Person类中的所有这些元素。

使用子类

可以使用其超类的地方使用子类。例如,使用上面定义的Employee和Person类,可以打开Employee对象并将其引用为Person:

 Set x = ##class(MyApp.Person).%OpenId(id)
 Write x.Name

我们还可以访问特定于Employee类的属性或方法:

Write x.Salary //显示Salary属性(仅在雇员实例中可用)

主要的父类

子类继承的最左边的超类称为它的主父类。继承了它的父类的所有成员,包括适用的类关键字、属性、方法、查询、索引、类参数以及继承属性和继承方法的参数和关键字。除了标记为Final的项外,子类可以覆盖(但不能删除)其继承成员的特征。

多重继承

通过多重继承,一个类可以从多个父类继承其行为和类类型。若要建立多重继承,请在括号内列出多个超类。最左边的超类是主父类。
例如,如果类X继承自类A、B和C,它的定义包括:

Class X Extends (A, B, C) 
{
}

类编译器的默认继承顺序是从左到右的,这意味着父类之间成员定义的差异将根据最左边的超类来解决(在本例中,A将取代B和C, B将取代C)

  • 具体来说,对于类X,类参数值、属性和方法的值继承自类A(列出的第一个超类),然后继承自类B,最后继承自类C。
  • X还继承了A没有定义的B的任何类成员,以及A和B都没有定义的C的任何类成员。
  • 如果B类有一个与从A继承的成员同名的类成员,则X使用从A继承的值;
  • 类似地,如果C有一个成员的名称与从A或B继承的成员的名称相同,则优先顺序为A、B、C。

因为从左到右的继承是默认的,所以不需要指定它;因此,前面的例子类定义等价于:

Class X Extends (A, B, C) [ Inheritance = left ]
{
}

要在父类之间指定从右到左的继承,请使用值为right的继承关键字:

Class X Extends (A, B, C) [ Inheritance = right ]
{
}

对于从右到左的继承,如果多个父类具有同名的成员,则右边的超类优先。

注意:即使使用从右到左的继承,最左边的父类(有时称为第一个父类)仍然是主父类。这意味着子类只继承它最左边的超类的class关键字值。

  • 例如,如果类X继承自类A、B和C,从右向左继承,如果从类A继承的成员与从类B继承的成员之间存在冲突,则类B继承的成员将覆盖(替换)以前继承的成员;C类的成员与A类和B类的成员之间的关系也是如此。
  • 类X的类关键字完全来自类A。
  • (这就是为什么用从左到右的继承顺序继承类A和B与用从右到左的继承顺序扩展类B和A是不同的;无论在哪个定义中,关键字都是从最左边的超类继承的,这使得两种情况不同。

注意:在Caché版本2010.1之前,继承顺序总是从右向左的,不能改变。由于类字典升级,来自已升级的旧实例的类将自动继续使用从右到左的继承。因此,现有的代码不需要任何更改,即使新类默认从2010.1开始使用从左到右的继承。

编译器关键字介绍

如“Defining a Class: The Basics,”中所示,可以在类定义或类成员定义中包含关键字。这些关键字,也称为类属性,通常会影响编译器。本节介绍一些常见的关键字,并讨Caché存如何表示它们。

例子

下面的例子展示了一个包含一些常用关键字的类定义:

/// 这个示例持久类表示一个person。
Class MyApp.Person Extends %Persistent [ SqlTableName = MyAppPerson ]
{

/// 为SSN属性定义唯一索引。
Index SSNKey On SSN [ Unique ];

/// Name of the person.
Property Name As %String [ Required ];

/// Person's Social Security number.
Property SSN As %String(PATTERN = "3N1""-""2N1""-""4N") [ Required ];

}

这个例子显示了以下关键字:

  • 对于类定义,Extends关键字指定该类继承的超类(或超类)。注意,以其他方式查看类时,Extends关键字有一个不同的名称;参见下一节。
  • 对于类定义,如果不使用默认名称,SqlTableName关键字将确定关联表的名称。这个关键字仅对持久类有意。
  • 对于索引定义,Unique关键字导致Caché对索引所基于的属性强制惟一性(本例中为SSN)。
  • 对于这两个属性,Required关键字导致Caché需要属性的非空值。
  • PATTERN不是一个关键字,而是一个属性参数;注意,模式是用括号括起来的,而不是方括号。

关键字及其值的表示

在许多情况下(但不是所有情况),当为类定义或类成员指定关键字时,将下列表单中的一个元素添加到类或类成员:

  • [ keyword ] 将关键字指定为true。
  • [ Not keyword ] 将关键字指定为false。
  • [ keyword=value ] 将关键字指定为给定值。
    在Studio Inspector中,编译器关键字及其值以不同的方式显示。例如,考虑以下类定义:
/// This sample persistent class represents a person.
/// <p>Maintenance note: This class is used by some of the bindings samples.
Class Sample.Person Extends (%Persistent, %Populate, %XML.Adaptor)
{

...

对于这个类,Studio Inspector显示以下关键字表:

在这里插入图片描述

注意,名称和描述都是关键字。如果在检查器中编辑Description, Studio将更新类定义中的注释,反之亦然。类似地,有一个名为Super的关键字,它指定该类父类。如果编辑它,Studio将更新类定义的Extends部分。

当显示类成员时,Studio检查器有类似的行为。在这种情况下,Inspector窗口将显示一个表,其中包含所有成员关键字和当前选中成员的那些关键字的值。(对于属性,Inspector窗口还列出可用的属性参数及其当前值。)

将类定义导出到XML时,导出的文件如下:

<Export generator="Caché" version="25" zv="Cache for Windows (x86-64) 2015.1 (Build 416U)" ts="2014-12-19 15:27:27">
<Class name="Sample.Person">
<Description><![CDATA[
This sample persistent class represents a person.
<p>Maintenance note: This class is used by some of the bindings samples.]]></Description>
<Super>%Persistent,%Populate,%XML.Adaptor</Super>
<TimeChanged>63540,49568.139638</TimeChanged>
<TimeCreated>59269,38836.623</TimeCreated>
 
<Parameter name="EXTENTQUERYSPEC">
<Default>Name,SSN,Home.City,Home.State</Default>
</Parameter>
 
...

该文件中的大多数XML元素都对应于编译器关键字。

当以编程方式访问类定义时,类定义实例包含与关键字对应的属性。

创建类的文档

Caché提供了一个称为InterSystems类引用的web页面,该页面显示由InterSystems提供的类以及创建的类自动生成的引用信息。通俗地说,类引用被称为documentation,因为它是由类%CSP.Documatic.生成的。

类引用

类引用的目的是向其他程序告知类的哪些部分可以使用,以及如何使用它们。以下是一个例子:

在这里插入图片描述

此参考信息显示类成员的定义,但不显示它们的实际实现。例如,它显示方法签名,但不显示其内部定义。它包括元素之间的链接,以便可以快速地遵循代码的逻辑;在某些情况下,这比使用Studio要快。还有一个搜索选项。

创建文档以包含在类引用中

要创建包含在类引用中的文档,请在类定义中创建注释—特别是以///开头的注释。如果在类声明之前加上这样的注释,则该类的注释将显示在页面的顶部。如果在给定的类成员之前加上这样的注释,则注释将显示在为该类成员生成的信息之后。
例如,在SAMPLES名称空间中,是Sample。Person类包括以下属性定义:

/// Person's Date of Birth.
Property DOB As %Date(POPSPEC = "Date()");

/// Person's age.<br>
/// This is a calculated field whose value is derived from <property>DOB</property>.
Property Age As %Integer [ Calculated, SqlComputeCode = { Set {Age}=##class(Sample.Person).CurrentAge({DOB})
}, SqlComputed, SqlComputeOnChange = DOB ];

将其与前面显示的类引用的图片进行比较。

默认情况下,表示将组合所有///行的文本,并将结果作为单个段落处理。可以插入HTML换行符。

注释的长度必须小于系统的最大字符串长度。

在类文档中使用HTML标记

可以在类中的注释中使用HTML标记。除了标准的HTML之外,还可以使用以下标记:类、方法、属性、参数、查询和示例。(与标准HTML标记一样,这些标记的名称不区分大小写。)这里描述了最常用的标记。

CLASS

用于标记类名。如果类存在,则内容将显示为类文档的链接。例如:

/// This uses the <CLASS>Sample.Person</CLASS> class.

EXAMPLE

用于标记编程示例。此标记影响文本的外观。请注意,在本例中,每一行都变成了单独的一行(与通常的情况不同,在这种情况下,行被合并成一个段落)。例如:

/// <EXAMPLE>
/// set o=..%New()
/// set o.MyProperty=42
/// set o.OtherProp="abc"
/// do o.WriteSummary()
/// </EXAMPLE>

METHOD

用于标记方法名。如果方法存在,内容将显示为方法文档的链接。例如:

/// This is identical to the <METHOD>Unique</METHOD> method.

PROPERTY

用于标记属性名。如果属性存在,则内容将显示为指向属性文档的链接。例如:

/// This uses the value of the <PROPERTY>State</PROPERTY> property.

下面是使用HTML标记的多行描述

/// The <METHOD>Factorial</METHOD> method returns the factorial
/// of the value specified by <VAR>x</VAR>.

编译类

Caché存类定义由Caché类编译器编译到应用程序例程中。类在编译之前不能在应用程序中使用。

Caché类编译器与其他编程语言(如c++或Java)中可用的编译器有两个重要的区别:首先,编译结果放在共享存储库(数据库)中,而不是文件系统中。其次,它自动提供对持久性类的支持。

具体来说,类编译器做以下工作:

  1. 生成一个依赖列表项——必须首先编译的类。根据使用的编译选项,自上次编译以来修改过的任何依赖项也将被编译。
  2. 解析继承——它确定从超类继承哪些方法、属性和其他类成员。它将这个继承信息存储到类字典中供以后参考。
  3. 于持久类和序列化类,它确定在数据库中存储对象所需的存储结构,并创建该类的SQL表示所需的必要运行时信息。
  4. 执行类定义(或继承)的任何方法生成器。
  5. 创建一个或多个包含类运行时代码的程序。(类编译器根据语言(Caché ObjectScript和Basic)将方法分组,并生成单独的程序,每个程序包含一种语言或另一种语言的方法。

如果使用类编译器指定了Keep Generated Source选项,可以在Studio中使用view Other Code命令(从view菜单中)查看例程的源代码。
6. 将所有生成的程序编译成可执行代码。
7. 创建了一个类描述符。这是一个特殊的数据结构(存储做为程序),包含支持类所需的所有运行时调度信息(属性名、方法位置等)。

调用类编译器

有几种方法来调用类编译器:

  • 在Caché Studio中使用Build菜单中的选项。
  • 从Caché命令行(在Caché终端中)使用 %SYSTEM.OBJ 对象:
 Do $System.OBJ.Compile("MyApp.MyClass")

如果使用SQL DDL(Data Definition Languages)语句创建表,则会自动调用类编译器来编译与表对应的持久类。

编译器注释

编译命令

在编译类时,如果正在编译的类包含有关依赖项的信息,那么Caché还将重新编译其他类。例如,Caché编译类的任意子类。在某些情况下,可能需要控制类编译的顺序。这样做,使用System,DependsOn和CompileAfter关键字。

要查找编译器将在编译给定类时重新编译的类, 使用$SYSTEM.OBJ.GetDependencies()方法。例如:

SAMPLES>d $system.OBJ.GetDependencies("Sample.Address",.included)
 
SAMPLES>zw included
included("SOAP.Demo.LookupCity")=""
included("SOAP.DemoProxy.LookupCity")=""
included("Sample.Address")=""
included("Sample.Customer")=""
included("Sample.Employee")=""
included("Sample.Person")=""
included("Sample.Vendor")=""

该方法的签名如下:

classmethod GetDependencies(ByRef class As %String, Output included As %String, qspec As %String) as %Status
  • 参数 class 可以是单个类名(如本例所示)、逗号分隔的类名列表,也可以是多维的类名数组。(如果它是一个多维数组,一定要通过引用传递这个参数。)它还可以包含通配符。
  • 参数 included 类的名称的多维数组,该类在编译时将被编译。
  • 参数 qspec是编译器标记和限定符的字符串。见下一小节。如果忽略这一点,则该方法将考虑当前编译器标志和限定符

查看类编译器标记和限定符

Compile()方法还允许提供影响结果的标志和限定符。它们在参数列表中的位置在Compile()方法的解释中进行了描述。要查看适用的标志,请执行以下命令:

 Do $System.OBJ.ShowFlags()

要查看限定符的完整列表,请执行以下命令:

Do $System.OBJ.ShowQualifiers()

编译包含位图索引的类

在编译包含位图索引的类时,如果没有为该类定义位图区段索引,则类编译器将生成位图区段索引。在向生产系统上的类添加位图索引时需要特别注意。

在内存中存在类的实例时进行编译

如果编译器在正在编译的类的实例打开时被调用,则不存在错误。已经打开的实例继续使用其现有代码。如果另一个实例在编译后打开,它将使用新编译的代码。

制造类部署

可能希望在将一些类发送给客户之前对它们进行部署;这个过程隐藏源代码。
对于包含不希望客户看到的方法定义的任何类定义,编译这些类,然后使用$SYSTEM.OBJ.MakeClassDeployed().。例如:

 d $system.OBJ.MakeClassDeployed("MyApp.MyClass")

关于部署模式

当类处于部署模式时,其方法和触发器定义已被删除。
可以在Studio中打开类定义,但它是只读的。
不能导出或编译已部署的类,但可以编译它的子类(如果没有部署的话)。
无法逆转或撤消类的部署。但是,如果以前导出过类,那么可以通过从文件中导入定义来替换该类。(如果不小心过早地将某个类放入部署模式,这将非常有用。)

发布了13 篇原创文章 · 获赞 1 · 访问量 364

猜你喜欢

转载自blog.csdn.net/yaoxin521123/article/details/104865324