TYPE TypeName [EXTENDS BaseTypeName] END TYPEThe example below defines the data type Tphone, containing the member variables Id, Name$ and Phone$.
TYPE Tphone INTEGER Id DIM Name$[30],Phone$[20] END TYPEThe example below defines the data type Tphone_ex. Since it is derived from the type Tphone, it includes all member variables of the base type. In addition, it adds the new member variable Comment$.
TYPE Tphone_ex EXTENDS Tphone DIM Comment$[40] END TYPEPlease note, that a base type can be defined after a derived type. It must be defined however before a derived type is instantiated.
In addition to a type definition in the program, data types can be defined from the database schema.
IN DATA SET data_set DEFINE TYPE type_nameWhere data_set is either a data set name or number and type_name is the name of the data type.
The example below defines the data type Tcustomer from the data set CUSTOMER.
DBOPEN(Db$,"",1,S(*)) ... IN DATA SET "CUSTOMER" DEFINE TYPE TcustomerA data type has a scope, defining its lifetime and visibility:
When defining user defined COM variables, the type definition
is deleted when LOADing another program. In order to retain the variable
values across programs, you must define an identical type in the new
program.
DIM and COM statements:
The example below defines the variables Phone1 and Phone2.
They are of type Tphone.
In addition, the NEW STRUCT statement can be used to create a
new, identical copy of the referenced object.
The STRUCT statement can also be used to copy the value of an
object:
For example:
The following statements can be used with STRUCT:
The IS A operator can be used to categorize an instance.
For example:
Type instantiation
Since a type definition is merely a blueprint rather than a real object,
it must be instantiated before it can be used.
This can either be done before execution by using the COM and
DIM statements or at runtime with the NEW statement.
COM Instance_name:Type_name
COM Instance_name AS Type_name
DIM Instance_name:Type_name
DIM Instance_name AS Type_name
The NEW statement:
NEW Instance_name:Type_name
NEW Instance_name AS Type_name
The Instance_name is the variable name and the Type_name is
the name of the data type. The instance name and data type name are either
separated by a colon or the keyword AS.
DIM Phone1:Tphone
NEW Phone2 AS Tphone
NEW STRUCT Instance_name=Instance_Name
The example below creates a new object named "Clone". It will be an exact
copy of the referenced object "Entry".
DIM Entry:Tphone
Entry.Name$="Joe Sample"
Entry.Phone$="(202) 243 1440"
NEW STRUCT Clone=Entry
Using member variables
Member variables can be used like any other variable. A member variable
is specified by giving the variable name (instance name) and the name
of the member variable, separated by a dot.
Phone1.Comment$="*Fancy Comment*"
PRINT Phone1.Comment$
In addition to accessing single variables, you can specify the whole
object at once. The example below prints all member variables of Entry.
PRINT STRUCT Entry
STRUCT A=B
When copying an object to another, both must be compatible.
Passing a struct to a subprogram or function
When calling a subprogram or function with a STRUCT argument, you can
pass an object either anonymously or specify a type name.
CALL Sub(STRUCT A)
...
SUB Sub(A {AS|:} TypeName)
SUB Sub(STRUCT A)
Like regular variables, types can either be passed by value or by reference.
When passed by value, a copy is passed to the subroutine.
TYPE Type
INTEGER I
END TYPE
!
DIM Inst:Type
Inst.I=0
CALL Sub(Inst)
PRINT Inst.I
CALL Sub((Inst))
PRINT Inst.I
STOP
!
SUB Sub(STRUCT A)
A.I=A.I+1
SUBEND
Instances can be passed to a SUBroutine either anonymous or with an
associated type.
For example:
! Define type Tsample
TYPE Tsample
INTEGER I
DIM X$[20]
END TYPE
! DIM variable A with type Tsample
DIM A AS Tsample
! Pass A to SUB
CALL Sub1(STRUCT A)
CALL Sub2(STRUCT A)
STOP
! Sub1 requires a type Tsample (or any derived type)
SUB Sub1(A AS Tsample)
PRINT A.I;A.X$
SUBEND
! Sub2 does accept an anoymous variable
SUB Sub2(STRUCT A)
PRINT A.I;A.X$
SUBEND
The STRUCT keyword
The STRUCT keyword can be used with some statements to operate
on the whole object instead of a single member variable. This is similar
to the Array(*) notation in HP Eloquence which causes an operation on
the whole array instead of a single element.
Runtime type identification
The TYPEOF$ function can be used to identify an instance.
X$=TYPEOF$(instance_name)
This returns the type name of the given instance.
IF instance_name IS A type_name THEN ...
If the instance is either of the specified type or derived from
it, the IS A operator returns nonzero.
TYPE Tbase
INTEGER A
END TYPE
TYPE Tderived EXTENDS Tbase
INTEGER Q
END TYPE
!
DIM Derived:Tderived,Base:Tbase
DISP "Base is of type ";TYPEOF$(Base)
DISP "Inst is of type ";TYPEOF$(Derived)
DISP "Base is a Tbase =";Base IS A Tbase
DISP "Base is a Tderived =";Base IS A Tderived
DISP "Derived is a Tbase =";Derived IS A Tbase
DISP "Derived is a Tderived =";Derived IS A Tderived
STOP
Data base integration
The user defined type concept is designed to operate with the
HP Eloquence data base. The IN DATA SET ... DEFINE TYPE
statement can be used to define data types from the data base schema
at runtime, the PACKFMT, IN DATA SET LIST and
IN DATA SET ... USE have been enhanced to support user
defined data types.
For example:
DBOPEN(Db$,"",1,S(*))
...
IN DATA SET "CUSTOMER" DEFINE TYPE Tcust
NEW Cust:Tcust
IN DATA SET "CUSTOMER" USE STRUCT Cust
...
DBGET(Db$,"CUSTOMER",7,S(*),"@",Buf$,Key$)
...
Of course, types can also be defined statically in your program:
TYPE Tcust
DIM No$[6]
DIM Name$[30]
...
END TYPE
DIM Cust:Tcust
!
DBOPEN(Db$,"",1,S(*))
...
IN DATA SET "CUSTOMER" USE STRUCT Cust
...
DBGET(Db$,"CUSTOMER",7,S(*),"@",Buf$,Key$)
...
XPACK and XUNPACK
The XPACK and XUNAPCK statements can operate on a
STRUCT. STRUCT is treated as a list of variables.
The XPACK statement packs each member variable in a buffer.
The XUNPACK statement unpacks to a user defined type if it
is passed as an argument to XUNPACK and the member variable
matches the name in the buffer.
Error Messages
The following runtime errors are used with types:
ERRN | Description |
---|---|
12 | Attempt to re-declare a variable or label |
13 | Array dimensions not specified or undefined type |
900 | Undefined base type |
901 | Nested types are not supported |
902 | Statement not allowed in type definition |
903 | Illegal or incomplete type definition |
! common block TYPE Tglobal INTEGER Iv DIM Xv$[18] INTEGER A(1:2) END TYPE ! COM Global:Tglobal READ STRUCT Global DATA 123,"COMMON",1,2 ! PRINT "Global.Iv=";Global.Iv PRINT "Global.Xv$=";Global.Xv$ PRINT "Global.A(*)=";Global.A(1);Global.A(2) CALL Sub STOP ! SUB Sub COM Global:Tglobal PRINT "Global.Iv=";Global.Iv PRINT "Global.Xv$=";Global.Xv$ PRINT "Global.A(*)=";Global.A(1);Global.A(2) SUBEND