First let’s talk about what in the world is a Accessor method. When you create a class and compile it every action that can be taken with the resulting object is generated into code. This code is held in routines that do all the work of performing those actions when working with an object. This includes assigning and retrieving a value from a property in the class. Simply put an Accessor method is this code that gets called to manipulate the class property. There are two for each property, one to “Get” the value and one to “Set” the value. The names of these methods are tied to the name of the property suffixed with either “Get” or “Set”. In a moment we will add a new HomePhone number Property to the Employee class we created on a previous tip. For this property there will be routines named HomePhoneGet and HomePhoneSet. These are normally completely hidden from you. However there are often cases where you want to manipulate the value of the property upon setting it or retrieving (Get) it. For this you need to provide your own copy of the Accessor methods. You can provide one or both methods depending on your needs.
For this tip we will setup a new property on an Employee class to hold the home phone number. We wish to have standard storage and retrieved formats. Specifically the stored value should be all numbers with no separation or punctuation. We can accept a value in any normal format for a phone number and have it converted to all number. The value retrieved should Always be seen as (nnn) nnn-nnnn[ xnnn]. The trailing xnnn is optional as indicated by the brackets [] surrounding it and will be used to indicate an extension. We are assuming US phone numbers only here to keep the example simple. Any portion of the phone number subsequent to the basic 10 digits will be considered an extension.
First let’s add the new property. It is easiest to add the property using the wizard in Studio. You would Go to the Class menu and select Add then Property. We will name this property HomePhone and use a type of %String. The last dialog window in this wizard asks if you want to override the Set and Get methods. This example will do both so the dialog will look like this:
Both the check boxes are check off. When we ‘finish’ the dialog we will get our property and methods added as follows:
Property HomePhone
As %String;
Method HomePhoneGet()
As %String [ ServerOnly = 1 ]
{
Quit ""
}
Method HomePhoneSet(Arg As %String)
As %Status [
ServerOnly = 1 ]
{
Quit $$$OK
}
You could also add these methods manually if you have an existing property or dislike using wizards. Just be sure to use the property argument and returns values as shown above. You also need to mark the methods as ServerOnly. Now let’s add our code, but first we will add the option for Language = MVBASIC so that we can use a language the MV group will be comfortable with.
These methods now look like this:
Method HomePhoneGet()
As %String [
Language = mvbasic,
ServerOnly = 1 ]
{
$xecute "set %zEmpPhone = i%HomePhone"
Phone = %zEmpPhone
FormattedPhone = "(":Phone[1,3]:") "
FormattedPhone := Phone[4,3]
if Len(Phone) > 6 then FormattedPhone :=
"-":Phone[7,4]
if len(Phone) > 10 then FormattedPhone :=
" Ext. ":Phone[11,999]
RETURN FormattedPhone
}
Method HomePhoneSet(Arg As %String)
As %Status [
Language = mvbasic,
ServerOnly = 1 ]
{
%zEmpPhone = OCONV(Arg,"MCN")
$xecute "set i%HomePhone = %zEmpPhone"
return $System->Status->OK()
}
You will note a couple of unusual lines of code in these examples. First when we want to work with the value of the property we are using a special reference to the ‘instance’ value. This is indicated by the ‘i%’ prefix on the property name. We cannot simply reference the property of the object as that will again try to call the Accessor method which would put us in an infinite loop until the stack space runs out and the process aborts. Inside the accessor method you must use the i%propertyname reference to work with that properties value.
This brings us to the second strange syntax: $xecute "set %zEmpPhone = i%HomePhone"
These i% references are not accepted by MVBasic as this could be a valid variable name. Therefore to access this and still use MVBasic we need to run just a little bit of Caché Object Script. That is what the $xecute statement does. Using this is similar to doing an MV Execute in that it pushes a level so variables set in that line of code would not be available to the calling routine. To get around that we assign the value to a Global variable called %zEmpPhone. Being global it is available anywhere in the current process which allows our program to gain access to the value we need. Of course we could also just write this whole process in Caché Object Script, however the intent of this tip is to show MV experience folks how to use these features.
For the sake of completeness here is those same two methods written in Caché Object Script.
Method HomePhoneGet()
As %String [
ServerOnly = 1 ]
{
set Phone = i%HomePhone
set FormattedPhone =
"("_$extract(Phone,1,3)_")
"
set FormattedPhone =
FormattedPhone_$extract(Phone,4,6)
if ($Length(Phone) > 6)
{
set FormattedPhone =
FormattedPhone_"-"_$extract(Phone,7,10)
}
if $Length(Phone) > 10
{
set FormattedPhone =
FormattedPhone_" Ext. "_$extract(Phone,11,*)
}
quit FormattedPhone
}
Method HomePhoneSet(Arg As %String)
As %Status [
ServerOnly = 1 ]
{
// this command removes all characters (*E) except numerics
set i%HomePhone =
$zstrip(Arg,"*E",,"0123456789")
quit $$$OK
}
Running an Example
Here are commands that demonstrate this new property and its impact. Note the format of the phone number being loaded and then how is it seen when retrieved.
MyAccount:;emp = "MVFILE.EMPLOYEE"->%New("Richard Taylor","08-15-2008")
MyAccount:;emp->HomePhone = "123 345-9876 x34354"
MyAccount:;crt emp->HomePhone
(123) 345-9876 Ext. 34354
Finally, here is the record as seen on disk. Note that the phone number in attribute 9 has no formatting applied at all.
0001 Richard Taylor
0002 14838
0003
0004
0005
0006
0007
0008
0009 123345987634354
Richard S Taylor
Sales Engineer
InterSystems Corporation
Office: 443-340-8614
FAX: 440-815-5805
![]()
Yes, the direction is to use the @ME syntax. So the reference would be @ME->i%HomePhone.