@GET_DEFAULT[][3.3.0] @GET_DEFAULT[name][3.3.0] code, executed when non-existing field is accessed for reading or non-existing method is called @SET_DEFAULT[name;value][3.4.1] code, executed when non-existing field is accessed for writing @GET[][3.3.0] @GET[access type][3.4.0] code, executed when class/object is used in different calling contexts
You can define default getter (@GET_DEFAULT[])-special getter, which will be executed when non-existing field is accessed for reading. The field name, which was accessed, will be available in method only one param.
Important: it is forbidden to work with default getter as with ordinary getter: if you try to write $DEFAULT you will receive an error message.
You can also specify default setter (@SET_DEFAULT)-special setter, which will be executed when non-existing fiels is accessing for writing. The field name, which was accessed and the written value will be available in method's params.
User-defined classes may have special getter @GET[], which will be executed when class/object is used in different calling contexts such as scalar context, expression, etc. The access type, which was used, will be available in the method only param. The access type values are: def, expression, bool, double, hash, table or file. Note: in construction $a[$b] method @GET[] is not executed.
Methods named like that define "property", which one can use as an ordinary variable:
Note: if writing or reading property is not needed, corresponding method may be ommited.
Important: it is forbidden to have both properties and variables with same name.
Example: age and e-mail Take a person. It is convenient to store it's birthday, but we often need to output the age. Person needs e-mail, but one can forget to check its validity.
Let class a handle persons, its properties "age" and "e-mail" allow us to hide unnecessary details:
@USE /person.p
@main[]
$person[^person::create[
$.name[John Dow]
$.birthday[^date::create(2000;6;3)]
]]
# can change, but they check us $person.email[john@dow.com]
$person.name ($person.email), age: $person.age<br />
Outputs:
John Dow (john@dow.com), age: 5<br />(will be older with time)
It is now allowed to change person's age:
#this will cause error!
$person.age(99)
It is not allowed to assign invalid e-mail values: #this will cause error!
$person.email[john#dow.com]
Definition of person class
Above example works with person class, one must define it and it's properties.
In web-space root create person.p file, put this code inside it:
@CLASS
person
@create[p]
$name[$p.name]
$birthday[$p.birthday] # "age" property @GET_age[][now;today;celebday]
$now[^date::now[]]
$today[^date::create($now.year;$now.month;$now.day)]
$celebday[^date::create($now.year;$birthday.month;$birthday.day)]
# numeric value of boolean expression: true=1; false=0
$result(^if($birthday>$today)(0)($today.year - $birthday.year - ($today<$celebday)))
# "e-mail" property
@SET_email[value]
^if(!^Lib:isEmail[$value]){
^throw[email.invalid;Incorrect e-mail: '$value']
}
#variable name must differ from property name!
$private_email[$value]
Example of class which issimilar to table class and has additional functionality @main[]
$t[^MyTable::create{a b
0a 0b
1a 1b
2a 2b
3a 3b}]
Object value in expression: ^eval($t)<br />
^^t.count: ^t.count[]<br />
Print content of the object: ^print[$t]<br />
<br />
Copy object and print ^^c.count[]:
$c[^MyTable::create[$t]]
^c.count[]<br />
Remove 2 lines starting with offset=1 and print content of the object:
^c.remove(1;2)
^print[$c]<br />
<br />
Create new table-object based on MyTable and print ^^z.count[]:
$z[^table::create[$t]]
^z.count[]<br />
@print[t]
^t.menu{$t.a=$t.b}[<br />]
Definition of MyTable class @CLASS
MyTable
@create[uParam]
^switch[$uParam.CLASS_NAME]{
^case[string;void]{$t[^table::create{$uParam}]}
^case[table;MyTable]{$t[^table::create[$uParam]]}
^case[DEFAULT]{^throw[MyTable;Unsupported type $uParam.CLASS_NAME]}
}
# method will return value in different calling contexts
@GET[sMode]
^switch[$sMode]{
^case[table]{$result[$t]}
^case[bool]{$result($t!=0)}
^case[def]{$result(true)}
^case[expression;double]{$result($t)}
^case[DEFAULT]{^throw[MyTable;Unsupported mode '$sMode']}
}
# method will handle access to the "columns"
@GET_DEFAULT[sName]
$result[$t.$sName]
# wrappers for all existing methods are required
@count[]
^t.count[]