Difference between revisions of "Language Reference/Properties"
m (Example Template) |
SergeMukhin (talk | contribs) |
||
(7 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
{{languageReferenceNavbar|Properties}} | {{languageReferenceNavbar|Properties}} | ||
Properties are named values associated with classes and objects. Actually they are syntactic sugar for get/set predicates for the property value. And in that sense they are a language incarnation of a frequently used programming pattern. | |||
=== Declaration === | === Properties Sections === | ||
A properties section declares a set of object or class properties in the current scope. | |||
<vipbnf><PropertiesSection> : | |||
class-opt properties <PropertyDeclaration>-dot-term-list-opt</vipbnf> | |||
The keyword <vp>class</vp> can be used only inside class implementations, since: | |||
* properties declared in an interface are always object properties and | |||
* properties declared in a class declaration are always class properties. | |||
=== Property Declaration === | |||
<vipbnf><PropertyDeclaration> : | <vipbnf><PropertyDeclaration> : | ||
<PropertyName> : <PropertyType> <FlowPattern>-list-opt | <PropertyName> : <PropertyType> <FlowPattern>-list-opt</vipbnf> | ||
<FlowPattern>: one of | <vipbnf><FlowPattern>: one of | ||
(i) | (i) | ||
(o)</vipbnf> | (o)</vipbnf> | ||
It is possible to get the value of a property that has the (o) flow, and it is possible to set the value of a property that has the (i) flow. | |||
If the flow patterns are not stated, both (i) and (o) are assumed, so it is possible bot to set and get the value of such properties. | |||
Though it is legal to state (i) and (o) simultaneously, it is considered better practice to omit them in the get+set case. | |||
{{example|Assume we declare them with an i/o pattern as: | |||
<vip>properties | |||
durationO : real (o). % a get only property | |||
durationI : real (i). % a set only property | |||
durationIO : real (i) (o). % a "full" property, which can both be set and get. | |||
duration : real. % equivalent to the declaration above and preferred.</vip>}} | |||
<vip>interface ip | In the sequel we will use the use the following example: | ||
{{example|<vip>interface ip | |||
properties | properties | ||
duration : | duration : real. | ||
initialized : boolean. | initialized : boolean (o). | ||
scale : | scale : real. | ||
end interface</vip> | end interface</vip> | ||
<vp>duration</vp> and <vp>scale</vp> are get+set properties, and <vp>initialized</vp> is a get-only property.}} | |||
Properties are used like fact variables. It is possible to qualify properties for with a scope name or an object. | |||
<vp>X</vp> is an object that supports the interface ip | {{example|<vp>X</vp> is an object that supports the interface <vp>ip</vp> | ||
<vip>X:duration := 5, | <vip>X:duration := 5, | ||
if X:initialized | if true = X:initialized then ... else ... end if, | ||
X:scale := | X:scale := 2.56, | ||
....</vip> | ....</vip> | ||
Inside an implementation of ip you access the properties as if they were facts. | Inside an implementation of a class that supports <vp>ip</vp> you access the properties as if they were facts. | ||
<vip>duration := 5, | <vip>duration := 5, | ||
if initialized | if true = initialized then ... else ... end if, | ||
scale := | scale := 2.56, | ||
....</vip> | ....</vip>}} | ||
=== Implementation === | === Implementation === | ||
A property is implemented by defining a function for getting the value and a predicate to set it. | |||
{{example| | |||
<vip>clauses | |||
% implementation of the get function of the duration property | |||
duration() = duration_fact. | |||
clauses | |||
duration | % implementation of the set predicate of the duration property | ||
duration(D):- duration_fact := D/ scale.</vip> | duration(D) :- | ||
duration_fact := D / scale.</vip>}} | |||
Alternatively the property can be implemented as a fact variable with the same name as the property. | |||
{{example| | |||
<vip>facts | <vip>facts | ||
initialized : boolean := false.</vip> | % the initialized property is implemented by a fact variable | ||
initialized : boolean := false. | |||
% the scale property is implemented by a fact variable | |||
scale : real := 1.2</vip>}} | |||
In this case the compiler will implicitly provide clauses that implement the get and set predicates. | |||
{{example|For the two fact variable implementations above the compiler will provide clauses corresponding to this | |||
<vip> | |||
clauses | |||
% implicit get clause for the initialized property | |||
initialized() = initialized. | |||
clauses | |||
% implicit get clause for the scale property | |||
scale() = scale. | |||
clauses | |||
% implicit set clause for the scale property | |||
scale(V) :- | |||
scale := V. | |||
</vip> | |||
As mentioned below it would not be legal to state these clauses in a program.}} | |||
It is illegal to have set and get predicates and a fact with the same name, meaning that a property is either implemented by programmer provided clauses or by a fact; mixed implementation is not possible. | |||
{{example|We want to send a '''changed''' event when the <vp>duration</vp> property changes value. Therefore we have to implement the property by predicates, and use a fact variable with an other name for storing the value. | |||
<vip>properties | <vip>properties | ||
duration : integer. | duration : integer. | ||
Line 72: | Line 120: | ||
sendChanged(). | sendChanged(). | ||
duration(_D).</vip> | duration(_D).</vip> | ||
It is not possible to use the <vp>duration</vp> predicates as predicates (they are not declared as predicates, but as a property; it is just the way the get and set of the property are implemented). | |||
But in the predicate names are "used" - so you cannot declare predicates <vp>duration\1</vp> or <vp>duration\0-></vp>.}} | |||
But in the predicate names are | |||
As mentioned above properties are always implemented by get/set predicates even when the program implement them by a fact variable. | |||
=== Properties from Interface === | === Properties from Interface === | ||
Line 111: | Line 138: | ||
<vipbnf><PropertiesFromInterface> : | <vipbnf><PropertiesFromInterface> : | ||
properties from <InterfaceName> < | properties from <InterfaceName> <PropertyName>-comma-sep-list-opt</vipbnf> | ||
<vpbnf><PropertiesFromInterface></vpbnf> can only be used in interface definitions. | <vpbnf><PropertiesFromInterface></vpbnf> can only be used in interface definitions. |
Latest revision as of 10:16, 10 July 2017
Properties are named values associated with classes and objects. Actually they are syntactic sugar for get/set predicates for the property value. And in that sense they are a language incarnation of a frequently used programming pattern.
Properties Sections
A properties section declares a set of object or class properties in the current scope.
PropertiesSection : class-opt properties PropertyDeclaration-dot-term-list-opt
The keyword class can be used only inside class implementations, since:
- properties declared in an interface are always object properties and
- properties declared in a class declaration are always class properties.
Property Declaration
PropertyDeclaration : PropertyName : PropertyType FlowPattern-list-opt
FlowPattern: one of (i) (o)
It is possible to get the value of a property that has the (o) flow, and it is possible to set the value of a property that has the (i) flow. If the flow patterns are not stated, both (i) and (o) are assumed, so it is possible bot to set and get the value of such properties.
Though it is legal to state (i) and (o) simultaneously, it is considered better practice to omit them in the get+set case.
properties durationO : real (o). % a get only property durationI : real (i). % a set only property durationIO : real (i) (o). % a "full" property, which can both be set and get. duration : real. % equivalent to the declaration above and preferred.
In the sequel we will use the use the following example:
interface ip properties duration : real. initialized : boolean (o). scale : real. end interface
Properties are used like fact variables. It is possible to qualify properties for with a scope name or an object.
X:duration := 5, if true = X:initialized then ... else ... end if, X:scale := 2.56, ....
Inside an implementation of a class that supports ip you access the properties as if they were facts.
duration := 5, if true = initialized then ... else ... end if, scale := 2.56, ....
Implementation
A property is implemented by defining a function for getting the value and a predicate to set it.
clauses % implementation of the get function of the duration property duration() = duration_fact. clauses % implementation of the set predicate of the duration property duration(D) :- duration_fact := D / scale.
Alternatively the property can be implemented as a fact variable with the same name as the property.
facts % the initialized property is implemented by a fact variable initialized : boolean := false. % the scale property is implemented by a fact variable scale : real := 1.2
In this case the compiler will implicitly provide clauses that implement the get and set predicates.
clauses % implicit get clause for the initialized property initialized() = initialized. clauses % implicit get clause for the scale property scale() = scale. clauses % implicit set clause for the scale property scale(V) :- scale := V.
It is illegal to have set and get predicates and a fact with the same name, meaning that a property is either implemented by programmer provided clauses or by a fact; mixed implementation is not possible.
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).
It is not possible to use the duration predicates as predicates (they are not declared as predicates, but as a property; it is just the way the get and set of the property are implemented).
But in the predicate names are "used" - so you cannot declare predicates duration\1 or duration\0->.As mentioned above properties are always implemented by get/set predicates even when the program implement them by a fact variable.
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 PropertyName-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.