Liu Kin Yeap electronic_whale@yahoo.com
March 2nd, 1999
Second update: July 14th, 1999
Condition of use
This guide is by no means complete and perfect. It is a generalisation as a result of reading other resources. It may contain errors. I am still working towards bettering this document. If you have any suggestions or you have spotted any errors please email me. This document can be distributed freely in its original form. All updates to this document must be sent to electronic_whale@yahoo.com.
if agree then continue_reading; else go_back; end if;
Assumed Knowledge
It is assumed that you already know how to write simple ADA code.
Introduction
A new language definition for ADA was completed in 1995 with the release of ADA95. For information on how to download the GNAT compiler please check out the newbies section.
ADA95 now provides support for object-oriented programming. What is object-oriented programming and how it is implemented in ADA95?
1. Type Extension
Type extension in ADA95 is achieved using 'tagged records'. Tagged records allows the original ADA record type to be extended from a foundation record. The foundation record must be specified as tagged.
For example:
package people is
type sex is (male,female);
type person is tagged record
name:string(1..35);
gender:sex;
end record;
function age (p:in person) return natural;
end people;
Now suppose we have another package call 'school' that uses specification from package 'people'.
with people; use people;
package school is
type janitor is new person with null record;
type teacher is new person with record
subject:string(1..5);
end record;
type head_master is new teacher with record
off_tel:natural;
room_num:natural;
end record;
end school;
Type 'janitor' is extended from the foundation type 'person'. It has the fields 'name', 'gender', but no additional fields are added since we wrote 'with null record'.
Type 'teacher' is extended from the foundation type 'person'. The extension 'teacher' has the basic fields 'name' and 'gender' as the foundation record type 'person'. In addition to the basic fields. A new field, 'subject' is added. This is called type extension and is only possible if the base or foundation type (person in this case) is declared as tagged.
Type 'head_master' is extended from type 'teacher'. Since the base type of 'teacher' is declared as tagged, it is possible to add fields to type 'head_master'. In this case, we have added the fields 'off_tel' and 'room_num'.
The declaration and assignment of variables derived from tagged records are as usual, but with one special property:
p:person;
t:teacher:=("gil",male,"ada95");
p:=person(t); --type conversion from type 'teacher' to type 'person'.
It is possible to cast a variable of its derived type to its foundation types. 't' is of type 'teacher', but we are able to cast is to its foundation type, 'person'.
1.1 Tagged Private
When using tagged private, the foundation type must be private and allows users to extend it.
For example:
package new_people is
type sex is (male,female);
type person is tagged private;
function age (p:person) return natural;
private
type person is tagged record
name:string(1..5);
gender:sex;
end record;
end new_people;
Note that the type 'person' is tagged private. That means it allows the user of the package 'new_people' to extend the type 'person' without knowing the details of the type.
For example:
with new_people; use new_people;
package user is
type star is new_person with record
cosmetic_surgery:boolean;
end record;
....
end user;
Type 'star' extends 'new_person' without knowing the details of the type (eg. what fields it contains).
1.3 Abstract Tagged Records
Abstract tagged records basically means declaring a base type for other types to derive from. It is however not possible to declare object of abstract tagged record type.
Here is an example:
package people is type person is abstract tagged null record; end people;
Meanwhile, in another package:
with people; use people;
package people.normal is
type sex is (male,female); -- Declaring enumerated type sex.
type normal_people is new person with record
home:string(1..5);
gender:sex;
end record;
end people.normal;
Note that the file name for the above package should be 'people-normal.ads', reflecting the fact that the package is a child of package 'people'.
Another package using people.
with people.normal; use people.normal;
package people.hollywood is
type star is new normal_people with record
cosmetic_surgery:boolean;
end record;
end people.hollywood;
Again, package 'people.hollywood' should be in file 'people-hollywood.ads'.
Type 'star' is extending from the base type or abstract tagged type 'person'.
2. Polymorphism
In ADA95, if we have a tagged type T, then we automatically have an associated type T'class, which contains the union of all types derived from the root type T.
For example, from the tagged type 'person', we have person'class which contains the union of all types derived from the root type 'person' (janitor,teacher,head_master).
What if we have a variable of a class wide type (eg. person'class)? How the run-time system is going to know how much space to allocate to a variable of a class wide type since the variable can the extended during the execution of the code?
Since person'class is an indefinite type. In order to declare an object of type person'class, it is compulsory to initialized it with the value of a specific type.
Extending from the examples above, the code below should illustrate this situation.
J:janitor; T:teacher; H:head_master; X:person'class:=T; --X is initialized with a value of a variable of type 'teacher'. X:=T; --this is valid. X:=H; --this is valid too because H is of type 'head_master', which is derived from type 'teacher'. X:=J; --this is NOT valid because variable X is not of type 'janitor' and --it is not derived from type 'janitor' either.
3. Dispatching
When performing function and procedure calling, the formal parameter can be a class wide type whereas the actual parameter can be any type derived from the class wide type. Hence, extending from our example above, we can write:
function calculate_age (P: in person'class) return natural is begin age(P); end age;
The function 'calculate_age' takes in an actual parameter derived from the class wide type person'class (eg. janitor, teacher, head_master) and dispatches it to the corresponding copy of the function age at run time.