Language Reference/Properties
The properties section declares a set of object or class properties in the current scope.
Declaration
PropertyDeclaration : PropertyName : PropertyType FlowPattern-list-opt. FlowPattern: one of (i) (o)
The properties are declared similar to single facts.
If flow patterns are skipped, both (i) and (o) are assumed.
For example:
interface ip properties duration : integer. initialized : boolean. scale : string. end interface
The properties are used exactly like single facts inside the implementation. It is possible to qualify properties for a scope name or object.
X is an object that supports the interface ip
X:duration := 5, if X:initialized = true then ... else ... end if, X:scale := "meter", ....
Inside an implementation of ip you access the properties as if they were facts.
duration := 5, if initialized = true then ... else ... end if, scale := "meter", ....
Implementation
You implement a property by defining a function for getting the value and an appropriate predicate to set it.
E.g.,
clauses duration() = duration_fact * scale. duration(D):- duration_fact := D/ scale.
Or as a fact with the same name as the property
facts initialized : boolean := false.
You cannot have set and get predicates and a fact with the same name. So if you want a fact, which stores the value of the property, which often is the case, you will have to give this fact another name e.g.:
properties duration : integer. facts duration_fact : integer. clauses duration() = duration_fact. clauses duration(D) :- OldDuration = duration_fact, duration_fact := D, OldDuration <> D, !, sendChanged(). duration(_D).
You cannot use the duration predicates as predicates (not surprisingly they are not declared as predicates, but as a property; it is just the way the get- and set-methods of the property are implemented).
But in the predicate names are taken - so you cannot declare a predicate duration\1 or duration\0->.
Implementation Detail
When you access a property declared in an interface, you cannot make any assumptions about how it is implemented; so you have to assume that it is implemented with predicates.
So if the programmer has defined the property as a fact, the compiler will have to generate the proper predicates. And use them, when accessing the property through an interface.
Inside the implementation, a property defined as a fact can be accessed simply as a fact.
Read or Write Restrictions
Sometimes you want to have a property, which can only be read or written to.
Assume we declare them with an i/o pattern as:
duration : integer (o). % a read only property duration : integer (i). % a write only property duration : integer (o) (i). % a normal property, which can be both written to and read from. This is equivalent to not writing anything duration : integer. % equivalent to the declaration above.
If a property is declared as a read-only property, you only need to declare the get predicate and likewise if it is declared as write-only only the set predicate.
Of course if you implement the property as a fact then the fact can be used as a normal fact inside the implementation.
Properties from Interface
An interface can support a subset of another interface by stating the properties in a properties from section. The properties from section names the interface and all supported properties.
If an interface supports a subset of another interface it is neither subtype or super-type related to the other interface.
The important thing about the properties from section is that the mentioned properties retain their origin interface. Therefore:
- there will be no support conflict with any properties from the origin interface;
- they can be inherited as the properties from the origin interface.
PropertiesFromInterface : properties from InterfaceName PpropertyName-comma-sep-list-opt
PropertiesFromInterface can only be used in interface definitions.
interface aaa properties pp : integer. qq : boolean. end interface aaa interface bbb properties from aaa pp properties rr : string. end interface bbb interface ccc supports aaa, bbb end interface ccc
Even though aaa and bbb both declare a property pp, ccc can support them both without any conflicts, because pp has aaa as an origin interface in all cases.
interface aaa properties pp : integer. qq : boolean. end interface aaa interface bbb properties from aaa pp properties rr : string. end interface bbb class aaa_class : aaa end class aaa_class class bbb_class : bbb end class bbb_class implement aaa_class inherits bbb_class facts pp_fact(): integer. clauses pp()= pp_fact-3. clauses pp(D):- pp_fact:=D+3. end implement aaa_class
aaa_class can inherit pp from bbb_class, because pp in both classes has aaa as origin interface.