类名和包
每个 Caché
类都有一个名称,该名称在定义它的命名空间中必须是唯一
的。完整的类名是由一个或多个句点
分隔的字符串,如以下示例所示:package.subpackage.subpackage.class
。短类名
是此字符串中最后一个句点之后的部分;最后一个句点前面的部分是包名称
。
包名称只是一个字符串,但如果包含句点,Caché 开发工具会将每个句点分隔的片段视为子包
。
类定义的基本内容
Caché
类定义可以包括以下项,所有这些项都称为类成员:
- 参数 — 参数定义供此类使用的常量值。该值在编译时设置。
- 方法 — 有两种方法:实例方法和类方法(在其他语言中称为静态方法)。在大多数情况下,方法是子例程。
- 属性 — 属性包含类实例的数据。
- 类查询 — 类查询定义可由类使用的 SQL 查询,并指定要用作查询容器的类。
- XData 块 — XData 块是类中格式正确的 XML 文档,供类使用。
这些有许多可能的应用。 - 仅与持久类相关的其他类型的类成员;这些将在下一章中讨论。
类定义可以包含关键字
;这些会影响类编译器的行为。您可以为整个类指定一些关键字,并为特定类成员指定其他关键字。这些关键字影响类编译器生成的代码,从而控制类的行为。
下面显示了一个简单的 Caché 类定义:
Class MyApp.Main.SampleClass Extends %RegisteredObject
{
Parameter CONSTANTMESSAGE [Internal] = "Hello world!" ;
Property VariableMessage As %String [ InitialExpression = "How are you?"];
Property MessageCount As %Numeric [Required];
ClassMethod HelloWorld() As %String
{
Set x=..#CONSTANTMESSAGE
Quit x
}
Method WriteIt() [ ServerOnly = 1]
{
Set count=..MessageCount
For i=1:1:count {
Write !,..#CONSTANTMESSAGE," ",..VariableMessage
}
}
}
- 第一行给出了类的名称。
MyApp.Main.SampleClass
是完整的类名,MyApp.Main
是包名,SampleClass
是短类名。 - 您无法编辑类名
Extends
是一个编译器关键字。
Extends
关键字指定此类继承%RegisteredObject
,这是一个系统类。此类仅继承一个类,但可以继承多个其他类。反过来,这些类也可以继承其他类。CONSTANTMESSAGE
是一个参数。按照惯例,Caché
系统类中的所有参数都具有全部大写的名称。这是一个方便的约定,但您不需要遵循它。
Internal
内部关键字是编译器关键字。它将此参数标记为internal
,这会禁止它在类文档中显示。此参数具有字符串值。VariableMessage
和MessageCount
是属性。As
后面的项指示这些属性的类型。InitialExpression
和Required
是编译器关键字。HelloWorld()
是一个类方法,它返回一个字符串;这由As
后面的项目指示。
此方法使用类参数的值。WriteIt()
是一个实例方法,它不返回值。
此方法使用类参数的值和两个属性的值。
ServerOnly
编译器关键字意味着此方法不会投影到 Java 或C++客户端。
以下终端会话显示了如何使用此类:
SAMPLES>write ##class(MyApp.Main.SampleClass).HelloWorld()
Hello world!
SAMPLES>set x=##class(MyApp.Main.SampleClass).%New()
SAMPLES>set x.MessageCount=3
SAMPLES>do x.WriteIt()
Hello world! How are you?
Hello world! How are you?
Hello world! How are you?
短类名应用场景
引用类时,可以在以下情况下省略包(或更高级别的包):
- 引用位于类中,引用的类位于同一包或子包中。
- 引用位于类中,该类使用 IMPORT 指令导入包含被引用类的包或子包。
- 引用位于方法中,并且该方法使用 IMPORT 指令导入包含引用的类的包或子包。
- 您引用的是 %Library 包。您可以参考该类
%Library.ClassName
as%ClassName
. 例如,可以将%Library.String
引用为%String
。 - 您引用的是User包。例如,您可以引用
User.MyClass
asMyClass
.
InterSystems
将User
包保留供您使用。
类参数
类参数定义一个值,该值对于给定类的所有对象都是相同的。此值在编译类时建立,不能在运行时更改
。将类参数用于以下目的:
- 定义不应在运行时更改的值。
- 定义有关类定义的特定于用户的信息。类参数只是一个任意的名称-值对;您可以使用它来存储您喜欢的有关类的任何信息。
- 自定义用作属性时各种数据类型类的行为(例如提供验证信息)
-为要使用的方法生成器方法提供参数化值。
下面显示了一个具有多个参数的类:
Class GSOP.DivideWS Extends %SOAP.WebService
{
Parameter USECLASSNAMESPACES = 1;
/// Name of the Web service.
Parameter SERVICENAME = "Divide";
/// SOAP namespace for the Web service
Parameter NAMESPACE = "http://www.mynamespace.org";
/// let this Web service understand only SOAP 1.2
Parameter SOAPVERSION = "1.2";
///further details omitted
}
属性
从形式上讲,Caché
中有两种属性:
- 保存值的属性。该值可以是以下任一值:
- 单个文本值,通常基于数据类型。
- 对象值(包括集合对象和流对象,两者都将在下一章中介绍)。
- 多维数组。这种情况不太常见。
“属性”一词通常仅指作为特性的属性,而不是包含关联的属性。
- 关系,用于保存对象之间的关联。
本节显示一个示例类,该类包含显示其中一些变体的属性定义:
Class MyApp.Main.Patient Extends %Persistent
{
Property PatientID As %String [Required];
Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");
Property BirthDate As %Date;
Property Age As %Numeric [Transient];
Property MyTempArray [MultiDimensional];
Property PrimaryCarePhysician As Doctor;
Property Allergies As list Of PatientAllergy;
Relationship Diagnoses As PatientDiagnosis [ Cardinality = children, Inverse = Patient ];
}
请注意以下几点:
- 在每个定义中,
As
后面的项是属性的类型。每种类型都是一个类
。语法As List Of
是特定集合类的简写;%String
、%Date
和%Numeric
是数据类型类。
%String
字符串是默认类型。 - 与其他文字属性不同,Age
不会保存到磁盘
。这是因为它使用了Transient
瞬态关键字。 MyTempArray
是一个多维属性,因为它使用MultiDimensional
多维关键字。默认情况下,此属性不会保存到磁盘
。PrimaryCarePhysician
和Allergies
是对象值属性。
属性关键字
在属性定义中,可以包括影响属性使用方式的可选属性关键字。以下列表显示了一些最常见的关键字:
-
Required
指定在此类的实例之前设置的属性值可以存储到磁盘。默认情况下,该属性不是必需的。在子类中,可以将可选属性标记为必需,但不能执行相反的操作。 -
InitialExpression
初始表达式:指定属性的初始值。默认情况下,属性没有初始值。子类继承InitialExpression
关键字的值,并且可以覆盖它。指定的值必须是有效的Caché ObjectScript
表达式(即使该类是用其他语言(如 Caché MVBasic)编写的,这也适用)。 -
Transient
短暂的,指定该属性不存储在数据库中。默认情况下,属性不是暂时性的。子类继承 Transient 关键字的值,并且不能覆盖它。 -
Private
指定属性为私有。子类继承 Private 关键字的值,并且不能覆盖它。
默认情况下,属性是公共的,可以在任何地方访问。您可以将属性标记为私有(通过 Private 关键字)。如果是这样,则只能通过它所属对象的方法访问它。
在 Caché 中,私有属性始终是继承的,并且对定义该属性的类的子类可见。
在其他编程语言中,这些属性通常称为受保护的属性。 -
Calculated
指定在实例化包含该属性的对象时,该属性没有为其分配内存中存储。默认情况下,不是计算属性。子类继承 Calculated关键字,并且不能覆盖它。 -
MultiDimensional
指定属性是多维的。此属性与其他属性不同,多维属性很少见,但偶尔可用于临时包含对象状态信息,如下所示:- 它没有关联的方法。
- 验证或保存对象时,将忽略它。
- 它不会保存到磁盘,除非您的应用程序包含专门保存它的代码。
- 它不能通过ActiveX或Java公开。
- 它不能存储在 SQL 表中或通过 SQL 表公开。
基于数据类型的属性
定义属性并将其类型指定为数据类型类时,可以使用特殊选项来定义和使用该属性,如本节所述。
数据类型类
数据类型类
使您能够强制实施有关属性值的规则集。
Caché
提供的数据类型类包括 %Library.String
、%Library.Integer
、%Library.Numeric
、%Library.Date
、%MV.Date
等。因为类的名称%Library
库包可以缩写,你可以缩写其中的许多;例如,%Date
是 %Library.Date
的缩写。
每个数据类型类都具有以下功能:
- 它指定编译器关键字的值。对于属性,编译器关键字可以执行如下操作:
- 使属性成为必需属性
- 指定属性的初始值
- 控制如何将属性投影到 SQL、ODBC、ActiveX 和 Java 客户端
- 它指定影响详细信息的参数值,如下所示:
- 数据类型允许的最大和最小逻辑值
- 字符串可以包含的最大和最小字符数
- 小数点后的数字位数
- 如果字符串超过最大字符数,是否截断字符串
- 显示格式
- 如何转义任何特殊的 XML 或 HTML 字符
- 要在任何用户界面中使用的逻辑值和显示值的枚举列表
- 字符串必须匹配的模式(自动使用 Caché 模式匹配运算符)
- 导入或导出到 XML 时是遵循还是忽略 UTC 时区
- 它提供了一组方法,用于在存储(磁盘上)、逻辑(内存中)和显示格式之间转换文本数据。
您可以添加自己的数据类型类。例如,下面显示了 %Char 的自定义子类:
Class MyApp.MyType Extends %Library.Char
{
/// The maximum number of characters the string can contain.
Parameter MAXLEN As INTEGER = 2000;
}
重写数据类型类的参数
定义属性并将其类型指定为数据类型类时,可以重写由该数据类型类定义的任何参数。
例如,%Integer 数据类型类定义类参数 (MAXVAL
),但不为此参数提供任何值。您可以在属性定义中重写它,如下所示:
Property MyInteger As %Integer(MAXVAL=10);
(在内部,这是有效的,因为数据类型类的验证方法是方法生成器
;当编译器为类生成代码时,将使用您提供的参数值。)
同样,%String
类型的每个属性都有一个排序规则类型,该类型确定值的排序方式(如大小写是否有效)。默认排序规则类型为 SQLUPPER
对于另一个示例,数据类型类定义了 DISPLAYLIST 和 VALUELIST 参数,您可以使用这些参数来指定要在用户界面中显示的选项及其相应的内部值:
Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");
使用实例变量
若要从对象的实例方法中访问属性的内存中值,可以使用以下内存中值语法:
Set i%Name = "Carl"
这将直接将“Carl
”设置为属性 Name
的内存中值,绕过 NameSet
访问器方法(如果存在)。变量 i%Name
是一个实例变量;请参阅 Using Caché Objects 中的“i% 语法”
使用其他属性方法
属性具有许多自动关联的方法。这些方法由数据类型类生成。
例如,如果我们定义一个类人具有三个属性:
Class MyApp.Person Extends %Persistent
{
Property Name As %String;
Property Age As %Integer;
Property DOB As %Date;
}
每个生成的方法的名称都是与继承的类中的方法名称连接的属性名称。例如,与 DOB 属性关联的一些方法是:
Set x = person.DOBIsValid(person.DOB)
Write person.DOBLogicalToDisplay(person.DOB)
其中 IsValid
是属性类的方法,LogicalToDisplay
是 %Date
数据类型类的方法。