|
Home|Management Portal|Index
|
Using Caché Objects
Properties
|
|
|
| Server:docs.intersystems.com |
| Instance:CACHE20081 |
|
User:UnknownUser |
|
|
Properties are the class members that define the state of an object. The manner in which you can access and manipulate the values of an object’s properties depends on the object’s class definition. Formally, there are two kinds of properties:
-
Attributes, which hold values
-
Relationships, which hold associations between objects
Within Caché, attribute properties are simply referred to as
properties while relationship properties are referred to as
relationships .
Many object languages such as Java and C++ do not have true properties, but rather private variables manipulated by public accessor methods. In Caché, properties are different from variables. There is a rich model for properties in which:
-
Properties can be literal values, collections of literal values, streams, references to persistent objects or embedded objects, or collections of references to persistent objects or embedded objects.
-
Properties automatically have a set of property methods supporting validation and storage.
-
Properties can transparently invoke sophisticated translations and other advanced functionality during data retrieval and storage.
-
Properties automatically pull embedded and persistent objects into memory as soon as they are referenced. This is called
swizzling (sometimes referred to as
lazy loading ).
Every property has a name, a type, an optional set of modifying keywords, and an optional set of parameters for its type. A property name must be unique within its class.
You can modify a property definition through the use of one or more property keywords. Each keyword is optional and has a default value if not explicitly specified.
The available property keywords include:
Specifies that the property has no in-memory storage allocated for it when the object containing it is instantiated. By default, a property is not calculated. Subclasses inherit the
Calculated keyword and cannot override it.
Provides an optional description of the property; Caché does not use this description. By default properties have no description. Subclasses do not inherit the value of the
Description property keyword.
Specifies that subclasses cannot override the property. By default, properties are not final. The
Final property keyword is inherited by subclasses.
Specifies an initial value for the property. By default, properties have no initial value. Subclasses inherit the value of the
InitialExpression keyword and can override it. The value specified must be a valid Caché ObjectScript expression (this is the case, even if the class is written in another language, such as MVBasic).
Specifies that the property is private. By default, properties are not private. Subclasses inherit the value of the
Private keyword and cannot override it.
Specifies that the property’s value must be set before it can be stored to disk. By default, properties are not required. Subclasses inherit the value of the
Required keyword and can override it.
Specifies that the property is not stored in the database. By default, properties are not transient. Subclasses inherit the value of the
Transient keyword and cannot override it.
Specifies the name of the class associated with the property, which can be a data type class, a persistent class, or an embeddable class. By default, the type of a property is
%String. Subclasses inherit the value of the
Type keyword.
Properties may be specified as being public or private. If they are public, they can be accessed anywhere. If they are private, they can only be accessed by instance methods of the object to which they belong.
Note:
Methods that are declared as class methods do
not have access to properties declared to be private, even if they have a reference to an object of the class they are declared in. Private properties are only accessible from within instance methods of the class.
In Caché, private properties are always inherited and visible to subclasses of the class that defines the property. Other languages often call these protected properties.
Properties have a number of methods associated with them automatically. These methods are not inherited via standard inheritance. Rather, they use a special property behavior mechanism to generate a series of methods for each property.
Each property inherits a set of methods from two places:
-
A
%Property class that provides certain built-in behavior, such as
Get,
Set, and validation code.
-
The data type class of the property’s data type, if it is a data type property. Many of these methods are method generators.
Property Behavior
The property behavior classes are system classes. You cannot specify or modify property behavior.
For example, if we define a class
Person with three properties:
Class MyApp.Person Extends %Persistent [ClassType = persistent]
{
Property Name As %String;
Property Age As %Integer;
Property DOB As %Date;
}
The compiled
Person class has a set of methods automatically generated for each of its properties. These methods are inherited from the system
Property class as well as the data type class associated with the property. The names of these generated methods are the property name concatenated with the name of the method from the inherited class. For example, some of the methods associated with the
DOB property are:
Set x = person.DOBIsValid(person.DOB)
Write person.DOBLogicalToDisplay(person.DOB)
The Caché dot syntax for referring to properties is an interface for a set of accessor methods to retrieve and set values. For each property, whenever the code refers to
oref.Prop (where
oref is an object and
Prop is a property), it is executed as if a system-supplied
PropGet or
PropSet method were invoked. For example:
acts as if the following method was called:
It is important to point out that in most cases, there are no actual
PropGet and
PropSet methods; access for simple properties is implemented directly within the Caché virtual machine for optimal performance. You can, however, provide
PropGet and
PropSet methods for a specific property. In this case, these accessor methods will be invoked at runtime automatically.
Typically, every property has process-private, in-memory storage allocated for it. The system-provided property accessors use this storage directly. Note that this object storage is not held in the local variable symbol table and is not affected by the
Kill command.
If you need to access the in-memory stored value of a property from within an instance method of an object, you can use the following in-memory value syntax:
This directly sets Carl as the in-memory value of the property
Name, bypassing the
NameSet accessor (if present).
An attribute property is a value associated with a specific object (as opposed to a relationship property which relates two or more objects). Such properties typically represent the state of a specific object instance.
A property’s type is determined by the class associated with the property (or by a keyword in the case of collection and multidimensional properties). By default, properties use the
%String data type.
There are several types of attribute properties, including:
-
-
-
-
-
Multidimensional properties
The simplest type of property is a data type property. This is a literal value whose behavior is controlled by the data type class associated with the property.
Property Count As %Integer;
You can use data type parameters to place constraints on the allowed values of data type properties. You can specify values for the data type class parameter as follows:
Property Count As %Integer(MAXVAL = 100);
To set a data type property value equal to the empty string, use code of the form:
Set object.Property = $C(0)
An
object-valued property is a reference to another object, either embedded or persistent. In either case, the value of the property is an OREF while in memory. On disk, a reference to a persistent object becomes an OID, while an embedded object becomes a single serialized string containing all of the embedded object’s properties.
For instance, if an object-valued property,
Doc, is of the type
Doctor (where
Doctor is either a persistent object or an embeddable object), the definition of
Doc is:
A
collection property is one that contains a group (or collection) of individual elements, all of the same type. To specify a collection property, place the collection type at the start of the property definition. Caché supports two kinds of collections, called List and Array collections. The property type determines the contents of the collection. For example, the following code defines a
Colors property which is a list collection of
%String values:
// Property Colors As List Of %String;
Property Colors As List Of %String;
Similarly, Caché supports object collections, as in the following
Doctors property which is an Array of references to
Doctor objects:
Property Doctors As Array Of Doctor;
When you create a collection, Caché gives it a set of methods through a collection object. Caché includes several kinds of collection objects, each one designed to operate on a different kind of collection:
Collection Objects
You can manipulate a collection property using the methods of the collection object associated with it. For example, you can perform operations on the
Colors property defined earlier, using the methods provided by the
%ListOfDataTypes class:
Do obj.Colors.Insert("Red")
Do obj.Colors.Insert("Green")
Do obj.Colors.Insert("Blue")
Streams are used to create properties containing large (greater than 32K) amounts of character or binary data. Binary streams contain the same sort of data as type
%Binary, and can hold large binary objects such as pictures. Character streams contain the same sort of data as type
%String, and are intended for storing large amounts of text. Stream data can be stored in either an external file or a global, depending on how the property is defined. For example, the following code defines a binary stream stored as a file, and a character stream stored as a global (the LOCATION parameter is optional):
Property Image As %FileBinaryStream(LOCATION = "C:/Images");
Streams provide numerous methods for manipulating the data they contain. See the chapter
Streams for more detailed information.
Multidimensional Properties
Properties can be marked as being
multidimensional . This gives the instance variable associated to the property all the characteristics of an array node, upon which array operations like
$ORDER could work. For instance:
Property abc [ MultiDimensional ];
The following are examples of available operations on
abc:
Set x = $DATA(obj.abc)
Set x = $DATA(obj.abc(3))
Set x = $GET(obj.abc(3))
Set x = $ORDER(obj.abc("hello",3))
KILL obj.abc
The property behavior and data type classes are not used to generate methods for multidimensional properties. Thus, a multidimensional property named
Kids has no
KidsGet,
KidsSet, or
KidsLogicalToDisplay methods. There is no validation on setting a property value.
Multidimensional properties cannot be exposed through ActiveX or Java. Multidimensional properties cannot be stored in or exposed through SQL tables. Also, multidimensional properties are transient, unless the application includes code to store their data.