A dummy's guide to object-oriented programming in ADA95

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.

back