Properties
Properties are members that are used as if they are public data members, but are actually implemented via special methods called accessors.
They are accessed using the same syntax as fields but do not designate storage locations.
Instead, properties have accessors that read, write, or compute their values.
Values can be reflected directly (or indirectly (filtered)) in or out of a backing variable or computed, It's entirely up to the accessor.
There are 3 keywords for defining a property:
get defines a readOnly property ( Can access its value but cant change it).
set defines a writeOnly property ( Can write a new value but cant read it).
pro defines a property that is both readable and writable.
Most commonly a property accessor uses a backing variable (field) which the accessor just reflects.
There is a special form to simplify this using a clause beginning with keyword from.
- from var
If the word following from is var the property will get or set its value unchanged
from a backing variable named the same as the property name with a single underscore prepended to it.- If the backing variable doesn't exist but there is an initial value assignment to the property or
a type declaration on the property, the backing variable will be implicitly created for you
- If the backing variable doesn't exist but there is an initial value assignment to the property or
- from <backingVarId>
Otherwise the word following the from must be the name of an existing backing store variable.
var _nLife = 47 # backing variable with (implicit) protected access pro nLife from var # property nLife uses backing var _nLife # above line same as pro nLife from _nLife # but can use a different backing variable name from the property name pro numLife from _nLife # or use a backing variable with different (also shortcutted) accessability var __nLife0 = 48 # private access pro nLife0 from var # use protected or private backing variable of same name #or alternatively property and backing variable explicitly named pro nLife from __nLife0
You can implicitly create (a protected) initialised backing variable and property in one line like
pro nLife from var = 47 # type inferred from initial value # or explicitly specifying type and initial value pro nLife from var as int = 47 # More commonly perhaps a set or get variant can be given in the same manner ## (assume above prop dcls not made, any one of below is also valid) get nLife from var get nlifeSource from nLife set nLife from var # name same as backing variable set nLifeSink from nlife # any name same or unrelated to backing variable
Finally if an accessor needs to translate, filter or modify in some way a backing variable or provide a virtual variable (computed)
there is a longer syntax variant where either of both the get and set accessors can be specified with a block of code to
store (setter) or generate (getter) the property value.
Within the setter code block in such a variant an implicit parameter (of the same type as the property) named value
is provided that has the value passed or assigned to the property.
var _seed = 21 # a calculated property pro nLife get return 70 - _seed set # implicit parameter 'value' contains the value given to set into the property require value >0 and value <65 _seed = value
Properties can have Attributes and the default access modifiers can be overridden explicitly if desired.
DocStrings describing the property are both allowed and encouraged.
There is a special type of property called an Indexor which allows an instance to be accessed
using an array offset like syntax e.g. coll[x] .
Usually this is implemented for classes that act as containers, for access to the contained items.
The syntax for indexors is as described above except that the property name is [] with indexes comma
separated (if multiple) between the [] and the accessors must be coded explicitly ( the from clause shorthand is not available).
Grammar
get <propName> [from {var, <backingVariableName>} [as <Type>] [= <initValue>] ] [has <AttributeList>] [is <accessModifier>] [<DocString>] set <propName> [from {var, <backingVariableName>} [as <Type>] [= <initValue>] ] [has <AttributeList>] [is <accessModifier>] [<DocString>] pro <propName> [from {var, <backingVariableName>} [as <Type>] [= <initValue>]] [has <AttributeList>] [is <accessModifier>] [<DocString>] # full accessor variant pro <propName> [has <AttributeList>] [is <accessModifier>] [<DocString>] get [...] return <value> set [...] # assign or otherwise do something with implicit arg "value" (passed in) #Indexors {pro,set,get} '[' <indexer expression> ']' [as <Type>] [has <AttributeList>] [is <accessModifier>] [<DocString>] [ get [...] return <value> set [...] # assign or otherwise do something with implicit arg "value" (passed in)
Examples
class TimePeriod var seconds as float32 is private pro hours as float32 get return .seconds / 3600 set .seconds = value * 3600 class Program def main is shared t = TimePeriod() # Assigning the hours property causes the 'set' accessor to be called. t.hours = 24 # Evaluating the hours property causes the 'get' accessor to be called. print "Time in hours: ", t.hours
class Employee var numberOfEmployees as int = 0 is shared var __counter as int = 0 is shared var _name = '' # A read-write instance property: pro name from var # A read-only static property: get counter from __counter is shared # Constructor: cue init base.init # Calculate the employee's number: __counter = .counter + 1 + .numberOfEmployees class MainClass def main is shared Employee.numberOfEmployees = 100 e1 = Employee() e1.name = "Claude Vige" print String.format("Employee number: {0}", Employee.counter) print String.format("Employee name: {0}", e1.name) # Output is #Employee number: 101 #Employee name: Claude Vige
Indexor example
class IdxColl var _coll = [] cue init base.init _coll = [1,2,3,'xx'] pro [idx as int] as Object get return _coll[idx] set _coll[idx] = value def main is shared c = ProColl() assert c[0] == 1 assert c[3] == 'xx' c[2] = 'yy' assert c[2] == 'yy'
Notes
See Also
Properties(C# Programming Reference)