Overriding Property Methods
This topic describes how to override property methods, which are the actual methods that InterSystems IRIS® data platform uses when you use OREFs to work with the properties of objects. These methods are not used when you access the data via SQL.
How Property Methods Are Defined
When a class has properties, the class compiler automatically generates a number of methods for each property and uses those internally. The names of the methods are based on the property names.
You can also use these methods directly.
For any given property, the property methods are generated via a special mechanism that uses logic from two places:
-
An internal property behavior class (not documented), which provides certain built-in property behavior, such as Get(), Set(), and validation code. There are different implementations based on the kind of property. Literal properties, object-valued properties, and serial object properties have different property behavior classes.
The property behavior classes are system classes. You cannot specify or modify property behavior.
-
The data type class used by the property, if applicable. Many of these methods are method generators.
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:
-
It must have the name PropertyNameGet, where PropertyName is the name of the corresponding property.
-
It takes no arguments.
-
Its return type must be the same as the type of the property.
-
It must return the value of the property.
-
To refer to the value of this property, this method must use the variable i%PropertyName. This name is case-sensitive.
Important:Within this getter method for a given property, do not use ..PropertyName syntax to refer to the value of that property. If you attempt to do so, the result is a <FRAMESTACK> error, caused by a recursive series of references. You can, however, use ..PropertyName to refer to other properties, because doing so does not cause any recursion.
The variable i%PropertyName is an instance variable. For more information on instance variables, see i%PropertyName.
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 %BooleanOpens in a new tab:
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:
-
It must have the name PropertyNameSet, where PropertyName is the name of the corresponding property.
-
It takes one argument, which contains the value of the property.
Specifically, this is the value specified in the SET command, when the property is being set.
-
It must return a %StatusOpens in a new tab value.
-
To set the value of this property, this method must set the variable i%PropertyName. This name is case-sensitive.
Important:Within this setter method for a given property, do not use ..PropertyName syntax to refer to the value of that property. If you attempt to do so, the result is a <FRAMESTACK> error, caused by a recursive series of references. You can, however, use ..PropertyName to refer to other properties, because doing so does not cause any recursion.
The variable i%PropertyName is an instance variable. For more information on instance variables, see i%PropertyName.
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 %StringOpens in a new tab. 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 %StringOpens in a new tab:
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 %RawString.. 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 %RawStringOpens in a new tab. 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 %RawString rather than Sample.USZipCode, so that it's possible
/// to override ZipGet() and ZipSet().
Property Zip As %RawString;
Method ZipGet() As %RawString [ 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 %RawString) 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