User Tools

Site Tools


reference_variables.htm
Navigation:  Language Reference > 3 - Variable Declarations > Special Data Types > ====== Reference Variables ====== Previous pageReturn to chapter overviewNext page

A reference variable contains a reference to another data declaration (its “target”). You declare a reference variable by prepending an ampersand (&) to the data type of its target (such as, &BYTE, &FILE, &LONG, etc.) or by declaring an ANY variable. Depending upon the target's data type, the reference variable may contain the target's memory address, or a more complex internal data structure (describing the location and type of target data).

Valid reference variable declarations:

&BYTE &SHORT &USHORT &LONG &ULONG &DATE &TIME
&REAL &SREAL &BFLOAT8 &BFLOAT4 &DECIMAL &PDECIMAL &STRING
&CSTRING &PSTRING &GROUP &QUEUE &FILE &KEY &BLOB
&VIEW &WINDOW ANY &USTRING &BSTRING &VARIANT

The &STRING, &CSTRING, &PSTRING, &DECIMAL, and &PDECIMAL declarations do not require length parameters, since all the necessary information about the specific target data item is contained in the reference itself. This means a &STRING reference variable may contain a reference to any length STRING variable.

A reference variable declared as &WINDOW can target an APPLICATION, WINDOW, or REPORT structure. References to these structures are internally treated as the same by the Clarion runtime library.

An ANY variable can contain a reference to any of the simple data types, and so, is equivalent to any of the above except &GROUP, &QUEUE, &FILE, &KEY, &BLOB, &VIEW, and &WINDOW.

Procedure Reference Variables

Clarion 11.13622 Sept. 4, 2020 - FEATURE: Reference variables of Procedure types are supported by the compiler, and corresponding support is added to the linker and RTL. For more see Clarion Sharp Blog post on August 25, 2020.

Reference Assignment

The &= operator executes a reference assignment statement (destination &= source) to assign the source's reference to the destination reference variable. You may also use a reference assignment statement in conditional expressions.

The NULL built-in variable is used to “un-reference” a reference variable or to detect an “un-referenced” reference variable in a conditional expression.

Reference Variable Usage

The label of a reference variable is syntactically correct every place in executable code where its target is allowed. This means that, any statement that takes the label of a WINDOW as a parameter can also take the label of an &WINDOW reference variable which has been reference-assigned a WINDOW structure.

When used in a code statement, the reference variable is automatically “dereferenced” to supply the statement with the value of its target. The only exception is reference assignment statements, when the reference assigns the reference to the data item it is referencing. For example:

Var1    LONG        !Var1 is a LONG
RefVar1 &LONG       !RefVar1 is a reference to a LONG
RefVar2 &LONG       !RefVar2 is also a reference to a LONG
  CODE  
  RefVar1 &= Var1    !RefVar1 now references Var1
  RefVar2 &= RefVar1 !RefVar2 now also references Var1
  RefVar1 &= NULL    !RefVar1 now references nothing

Reference Variable Declarations

Reference variables may not be declared within FILE or VIEW structures, but they may be declared within GROUP, QUEUE, and CLASS structures. Issuing CLEAR(StructureName) for a GROUP, QUEUE, or CLASS structure containing a reference variable is equivalent to reference assigning NULL to the reference variable.

Global references cross thread boundaries, and so, may be used to reference data items in other execution threads.

A reference variable used in any attribute of a control, field, WINDOW or REPORT declaration must receive its value (i.e., a reference to some typed allocated storage) before processing this declaration on enter to the scope where it is declared. For example, if a WINDOW is declared in a procedure, the reference variable can be declared and receive its value before entry into the procedure, or be declared in the same procedure before the WINDOW and receive its value in the constructor of some class declared before the WINDOW.

Named QUEUE and CLASS References

In addition to the data types listed above, you may also have references to “named” QUEUEs (&QueueName) and to named CLASSes (&ClassName). This allows you to use references to pass “named group” parameters, which allow the receiving procedure access to the component fields of the named structure.

A reference to a named QUEUE or CLASS may be a “forward reference.” That is, the named QUEUE or CLASS does not have to have been declared previous to the reference variable declaration which “points at” it. However, the forward reference must be resolved before the reference variable can be used. In the case where the reference variable is contained within a CLASS declaration, the forward reference must be resolved before the object is instantiated, else the reference will be blank and unusable.

There are several advantages to using forward references. You can have a QUEUE of object references which each contains a reference to a QUEUE of object references which each contains a reference to a QUEUE of object references … For example, you could create a queue of siblings within a CLASS structure like this:

FamilyQ     QUEUE
Sibling      &FamilyClass     !A forward reference
           END
FamilyClass CLASS
Family       &FamilyQ       !
           END

Another advantage is the ability to truly “hide” the targets of PRIVATE references in CLASS declarations. For example:

!An include file (MyFile.inc) contains:
WidgetManager CLASS,TYPE
WidgetList     &WidgetQ,PRIVATE !
DoSomething    PROCEDURE
             END
!Another file (MyFile.CLW) contains:
MEMBER('MyApp')
INCLUDE('MyFile.INC')
WidgetQ     QUEUE,TYPE
Widget       STRING(40)
WidgetNumber LONG
           END
MyWidget   WidgetManager  !Actual instantiation must follow
                         ! forward reference resolution
MyWidget.DoSomething  PROCEDURE
  CODE
  SELF.WidgetList &= NEW(WidgetQ) !Valid code
  SELF.WidgetList.Widget = 'Widget One'
  SELF.WidgetList.WidgetNumber = 1
  ADD(SELF.WidgetList)

In this example, references to SELF.WidgetList are valid only within the MyFile.CLW file. Example:

App1   APPLICATION('Hello')
      END
App2   APPLICATION('Buenos Dias')
      END
AppRef &WINDOW  !Reference to an APPLICATION, WINDOW, or REPORT
Animal    CLASS
Feed       PROCEDURE(SHORT amount),VIRTUAL
Die        PROCEDURE
Age        LONG
Weight     LONG
         END
Carnivore CLASS(Animal),TYPE
Feed       PROCEDURE(Animal)
         END
Cat       CLASS(Carnivore)
Feed       PROCEDURE(SHORT amount),VIRTUAL
Potty      BYTE
         END
Bird      Animal              !Instance of an Animal CLASS
AnimalRef &Animal             !Reference to an Animal CLASS
  CODE
  IF CTL:Language = 'Spanish'  !If spanish language user
   AppRef &= App2              ! reference spanish application frame
  ELSE
   AppRef &= App1              ! else reference english application frame
  END
  OPEN(AppRef)                 !Open the referenced application frame window
  IF SomeCondition
   AnimalRef &= Cat            !Reference the Cat
  ELSE
   AnimalRef &= Bird           !Reference the Bird
  END
  AnimalRef.Feed(10)           !Feed whatever is referenced

NoteBox.jpg

In Clarion.NET, we have removed the requirement to use & to declare a reference to an object in the data section. See the New in Clarion# topic for more information.

See Also:

Reference Assignment Statements

CLASS

GROUP

QUEUE

ANY

reference_variables.htm.txt · Last modified: 2021/04/15 13:30 (external edit)