Using Caché Objects
Using and Overriding Property Methods
[Back] [Next]
   
Server:docs1
Instance:LATEST
User:UnknownUser
 
-
Go to:
Search:    

This chapter describes property methods, which are the actual methods that Caché uses when you use OREFs to work with the properties of objects. It discusses the following topics:

When viewing this book online, use the preface of this book to quickly find related topics.
Introduction to Property Methods
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:
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
{
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)
where IsValid() is a method of the property class and LogicalToDisplay() is a method of the %Date data type class.
Property Accessors for Literal Properties
The Caché dot syntax for referring to object properties is an interface for a set of accessor methods to retrieve and set values. For each non-calculated 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:
 Set person.DOB = x
acts as if the following method was called:
 Do person.DOBSet(x)
while:
 Write person.Name
acts like:
 Write person.NameGet()
In most cases, you cannot see the 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, as long as that property is not object-typed or multidimensional. If you define these methods, Caché automatically invokes them at runtime. The following sections describe how to define these accessor methods. Within the custom methods, you can perform any special processing that your application requires.
Note that the last screen of the New Property Wizard in Studio provides options for creating a custom Get() method, Set(), or both. If you use these options, Studio defines stub methods with suitable signatures.
Property Accessors for Object-Valued Properties
For every reference property there are SetObject() (using OID value) and SetObjectId() (using ID value) methods. For example, to assign a particular saved Person object as the owner of a Car object, use the following code:
 Do car.OwnerSetObjectId(PersonId)
where car is the OREF of the Car object and PersonId is the ID of the saved Person object.
There are also GetObject() and GetObjectId() methods, which get the OID or ID associated with the reference property, respectively. Taken all together, the various methods are:
Overriding a Property Getter Method
To override the getter method for a property, modify the class that contains the property and add a method as follows:
Note:
Note that it is not supported to override accessor methods for object-typed properties or for multidimensional properties. Also because the maximum length of a method name is 220 characters, it is not possible to create accessor methods for properties that are 218, 219, or 220 characters long.
The following shows an example, a setter method for a property named HasValue, which is of type %Boolean:
Method HasValueGet() As %Boolean 
{
  If ((i%NodeType="element")||(i%NodeType="")) Quit 0
  Quit 1
}
Overriding a Property Setter Method
To override the setter method for a property, modify the class that contains the property and add a method as follows:
Note:
Note that it is not supported to override accessor methods for object-typed properties or for multidimensional properties. Also because the maximum length of a method name is 220 characters, it is not possible to create accessor methods for properties that are 218, 219, or 220 characters long.
For example, suppose that MyProp is of type %String. We could define the following setter method:
Method MyPropSet(value as %String) As %Status
{
    if i%MyProp="abc" {
        set i%MyProp="corrected value"
    }
    quit $$$OK
}
The following shows another example, a setter method for a property named DefaultXmlns, which is of type %String:
Method DefaultXmlnsSet(value As %String) As %Status
{
    set i%DefaultXmlns = value
    If ..Namespaces'="" Set ..Namespaces.DefaultXmlns=value
    quit $$$OK
}
Notice that this example refers to the Namespaces property of the same object by using the ..PropertyName syntax. This usage is not an error, because it does not cause any recursion.
Defining an Object-Valued Property with a Custom Accessor Method
As noted earlier, it is not supported to override accessor methods for object-typed properties. If you need to define a property that holds object values and you need to define custom accessor methods, define the property with the type %CacheString. This is not an object class but is rather a generic class, and it is permitted to override the accessor methods for this property. When using the property, set it equal to an instance of the desired class.
For example, the following class includes the property Zip, whose formal type is %CacheString. The property description indicates that the property is meant to be an instance of Sample.USZipCode. The class also defines the ZipGet() and ZipSet() property methods.
Class PropMethods.Demo Extends %Persistent
{

/// Timestamp for viewing Zip
Property LastTimeZipViewed As %TimeStamp;

/// Timestamp for changing Zip
Property LastTimeZipChanged As %TimeStamp;

/// When setting this property, set it equal to instance of Sample.USZipCode.
/// The type is %CacheString rather than Sample.USZipCode, so that it's possible 
/// to override ZipGet() and ZipSet().
Property Zip As %CacheString;

Method ZipGet() As %CacheString [ ServerOnly = 1 ]
{
    // get id, swizzle referenced object
    set id = i%Zip
    if (id '= "") {
        set zip = ##class(Sample.USZipCode).%OpenId(id)
        set ..LastTimeZipViewed = $zdt($zts)
    }
    else {
        set zip = ""
    }
    return zip
}

Method ZipSet(zip As %CacheString) As %Status [ ServerOnly = 1 ]
{
    // set i% for new zip
    if ($isobject(zip) && zip.%IsA("Sample.USZipCode")) {
        set id = zip.%Id()
        set i%Zip = id
        set ..LastTimeZipChanged = $zdt($zts)
    }
    else {
        set i%Zip = ""
    }
    quit $$$OK
}

}
The following Terminal session demonstrates the use of this class:
SAMPLES>set demo=##class(PropMethods.Demo).%New()
 
SAMPLES>write demo.LastTimeZipChanged
 
SAMPLES>set zip=##class(Sample.USZipCode).%OpenId(10001)
 
SAMPLES>set demo.Zip=zip
 
SAMPLES>w demo.LastTimeZipChanged
10/14/2015 19:21:08