This chapter discusses objects in Caché. It discusses the following topics:
Introduction to Caché Object Classes
The following figure shows the inheritance relationships among these classes, as well as some of their parameters and methods. The names of classes of the %Library
package can be abbreviated, so that (for example) %Persistent
is an abbreviation for %Library.Persistent
. Here, the items in all capitals are parameters and the items that start with percent signs are methods.
In a typical class-based application, you define classes based on these classes (and on specialized system subclasses). All objects inherit directly or indirectly from one of these classes, and every object is one of the following types:
Basic Features of Object Classes
With the object classes, you can perform the following tasks, among others:
You can define properties in any class, but they are useful only in object classes, because only these classes enable you to create instances.
Any property contains a single literal value, an object (possibly a collection object), or a multidimensional array (rare). The following example shows the definition of an object-valued property:
Property Home As Sample.Address;
is another class. The following shows one way to set the value of the Home
Set myaddress.Street="15 Winding Way"
You can invoke methods of an instance of the class, if the class or its superclasses define instance methods. For example:
Write !, "Name: ", ..Name
is an instance of the class that defines this method, you can invoke this method as follows:
You can validate that the property values comply with the rules given in the property definitions.
All objects inherit the instance method %NormalizeObject()
, which normalizes all the object's property values. Many data types allow different representations of the same value. Normalization converts a value to its canonical, or normalized, form. %NormalizeObject()
returns true or false depending on the success of this operation.
All objects inherit the instance method %ValidateObject()
, which returns true or false depending on whether the property values comply with the property definitions.
All persistent objects inherit the instance method %Save()
. When you use the %Save()
instance method, the system automatically calls %ValidateObject()
In contrast, when you work at the routine level and do not use classes, your code must include logic to check the type and other input requirements.
You can define callback methods
to add additional custom behavior when objects are created, modified, and so on.
For example, to create an instance of a class, you invoke the %New()
method of that class. If that class defines the %OnNew()
method (a callback method
), then Caché automatically also calls that method. The following shows a simple example:
Method %OnNew() As %Status
Write "hi there"
In realistic scenarios, this callback might perform some required initialization. It could also perform logging by writing to a file or perhaps to a global.
method of an object class creates an internal, in-memory structure to contain the object’s data and returns an OREF
) that points to that structure. An OREF is a special kind of value in ObjectScript. You should remember the following points:
In the Terminal, when you display an OREF, you see a string that consists of a number, followed by an at sign, followed by the name of the class. For example:
Caché returns an error if you do not use an OREF where an OREF is expected:
SAMPLES>set myobj.Name="Fred Parker"
SET myobj.Name="Fred Parker"
It is helpful to be able to recognize this error. It means that the variable is not an OREF but should be.
There is only one way to create an OREF: Use a method that returns an OREF. The methods that return OREFs are defined in the object classes or their subclasses.
The following does not create an OREF, but rather a string that looks
like an OREF:
You can determine programmatically whether a variable contains an OREF. The function $IsObject
returns 1 (true) if the variable contains an OREF; and it returns 0 (false) otherwise.
As noted earlier
, Caché allocates a fixed amount of space to hold the results of string operations. If a string expression exceeds the amount of space allocated, a <MAXSTRING> error results. Unless long strings
are enabled, this limit is 32 KB and no string property can be larger than about 32 KB. (No other property can exceed this limit, either, but other restrictions take effect before the long string limit applies.)
If you need to pass a long string value, or you need a property to contain a long string value, you use a stream. A stream
is an object that can contain a single value whose size is larger than the string size limit. (Internally Caché creates and uses a temporary global to avoid the memory limitation.)
You can use stream fields with Caché SQL, with some restrictions. For details and a more complete introduction, see Using Caché Objects
; also see the InterSystems Class Reference for these classes.
The main Caché stream classes use a common stream interface defined by the %Stream.Object
class. You typically use streams as properties of other objects, and you save those objects. Stream data may be stored in either an external file or a Caché global, depending on the class you choose:
To work with a stream object, you use its methods. For example, you use the Write()
method of these classes to add data to a stream, and you use Read()
to read data from it. The stream interface includes other methods such as Rewind()
For example, the following code creates a global character stream and writes some data into it:
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: ",!
When you need a container for sets of related values, you can use $LIST format lists and multidimensional arrays, as described earlier in this book.
If you prefer to work with classes, Caché provides list classes and array classes; these are called collections
List and Array Classes for Use As Standalone Objects
To create list objects, you can use the following classes:
To manipulate a list object, use its methods. For example:
Write "Number of items in this list: ", Colors.Count()
Write !, "Second item in the list: ", Colors.GetAt(2)
Similarly, to create array objects, you can use the following classes:
To manipulate an array object, use its methods. For example:
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")
List and Arrays as Properties
You can also define a property as a list or array.
To define a property as a list, use the following form:
Property MyProperty As list of Classname;
To define a property as an array, use the following form:
Property MyProperty As Array of Classname;
Useful ObjectScript Functions
ObjectScript provides the following functions for use with object classes:
enables you to run a class method, given as class name and method name. For example:
Van De Griek,Charlotte M.
This function is useful when you need to write generic code that executes a class method, but the class name (or even the method name) is not known in advance. For example:
//read name of class from imported document
// create header object
The other functions are useful in similar scenarios.
enables you to run an instance method, given an instance and a method name. For example:
Name: Van De Griek,Charlotte M.
gets or sets the value of the given property for the given instance. For example:
gets the value of the given class parameter, given an instance. For example:
returns the class name for a given instance. For example:
With no argument, this function returns the class name of the current context. This can be useful in instance methods.
For more information on the topics covered in this chapter, see the following books: