Question
· Jan 28, 2022

Are immutable properties supported in ObjectScript classes?

Can we make any property immutable once it value is set? For example, I may have a property called RecordCreatedTime to track when the record is created in IRIS, and once it is set, I don't want anyone to modify the value. 

Product version: IRIS 2021.1
Discussion (4)0
Log in or sign up to continue

1. If it's a one-off thing redefine your property setter:

Class Test.RO Extends %Persistent
{

Property RecordCreatedTime As %TimeStamp [ InitialExpression = {$ZDATETIME($ZTIMESTAMP, 3, 1, 3)} ];

Method RecordCreatedTimeSet(value As %TimeStamp) As %Status
{
	if i%RecordCreatedTime="" {
		set i%RecordCreatedTime=value
	}
	quit $$$OK
}

/// do ##class(Test.RO).test()
ClassMethod test()
{
	set obj = ..%New()
	write obj.RecordCreatedTime,!
	
	set obj.RecordCreatedTime = "2000-01-01 00:00:01"
	write obj.RecordCreatedTime,!
}
}

It's also automatically set during object creation courtesy of InitialExpression, you can remove it if you want to set the value yourself.

2. If you have the same immutable property or a set of immutable properties you can write an abstract class:

Class Test.Base [Abstract]
{

Property RecordCreatedTime As %TimeStamp [ InitialExpression = {$ZDATETIME($ZTIMESTAMP, 3, 1, 3)} ];

Method RecordCreatedTimeSet(value As %TimeStamp) As %Status
{
	if i%RecordCreatedTime="" {
		set i%RecordCreatedTime=value
	}
	quit $$$OK
}
}

And add it to inheritance whenever you need:

Class Test.RO Extends (%Persistent, Test.Base)
{
}

3. Finally if you have a lot of immutable properties and they are all different you'll need a custom datatype. Custom datatype defines method generators for getters, setters and all other property methods. Let's inherit from %String so we only need to redefine a setter:

Class Test.ROString Extends %String
{

/// Generate Setter
Method Set(%val) [ CodeMode = objectgenerator, NoContext ]
{
	quit:%mode'="propertymethod" $$$OK
	do %code.WriteLine($c(9) _ "if i%" _ $g(%member) _ "="""" {")
	do %code.WriteLine($c(9,9) _ "set i%" _ $g(%member) _ "=%val")
	do %code.WriteLine($c(9) _ "}")
	do %code.WriteLine($c(9) _ "quit $$$OK")
	quit $$$OK
}

}

Now we create a property of Test.ROString type:

Class Test.RO Extends %Persistent
{
Property RecordCreatedTime As Test.ROString [ InitialExpression = {$ZDATETIME($ZTIMESTAMP, 3, 1, 3)} ];
}

And it would be immutable. In fact if we check a generated setter:

zRecordCreatedTimeSet(%val) public {
    if i%RecordCreatedTime="" {
        set i%RecordCreatedTime=%val
    }
    quit 1 }

It would look quite similar to what I have wrote in (1), only automatically generated.