Difference between revisions of "Language Reference/Properties"

From wiki.visual-prolog.com
(rephrase)
 
(One intermediate revision by one other user not shown)
Line 97: Line 97:


clauses
clauses
     % implicit get clause for the scale property
     % implicit set clause for the scale property
     scale(V) :-
     scale(V) :-
         scale := V.
         scale := V.
Line 138: Line 138:


<vipbnf><PropertiesFromInterface> :
<vipbnf><PropertiesFromInterface> :
     properties from <InterfaceName> <PpropertyName>-comma-sep-list-opt</vipbnf>
     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.

Example Assume we declare them with an i/o pattern as:
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:

Example
interface ip
properties
   duration : real.
   initialized : boolean (o).
   scale : real.
end interface
duration and scale are get+set properties, and initialized 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.

Example X is an object that supports the interface ip
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.

Example
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.

Example
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.

Example For the two fact variable implementations above the compiler will provide clauses corresponding to this
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.
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 duration 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.
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.

Example
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.

Example
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.