Abstract types
This tutorial will show you what an abstract type is in Ada. I will also provide information on how the Ada type equates to the C++ class.
An abstract type provides the "specification" for a family of a user defined types. When this type is derived from, the programmer must specify the operations that are defined as abstract.
Say we have a simple vehicle which can change gears, accelerate and brake. We're not interested in knowing what speed we're going, just the basics. In C++ a Vehicle pure virtual class could be defined:
C++ code
class Vehicle {
virtual bool GearUp() = 0;
virtual bool GearDown() = 0;
virtual void Accelerate() = 0;
virtual void Brake() = 0;
};
This can then be derived from to create a number of concrete vehicles:
C++ code
class Car : public Vehicle {
bool GearUp();
bool GearDown();
void Accelerate();
void Brake();
};
bool Car::GearUp() {
// Change the car's gears.
}
// etc.
class Van : public Vehicle {
bool GearUp();
bool GearDown();
void Accelerate();
void Brake();
};
bool Van::GearUp() {
// Change the van's gears.
}
// etc.
class Scooter : public Vehicle {
bool GearUp();
bool GearDown();
void Accelerate();
void Brake();
};
bool Scooter::GearUp() {
// Change the scooter's gears.
}
// etc.
Now, in Ada95 we use an abstract tagged type to implement the Vehicle type:
Ada95 code
package Vehicle is
type Vehicle_Type is abstract tagged private;
function Gear_Up(
Self : Vehicle_Type) return Boolean is abstract;
function Gear_Down(
Self : Vehicle_Type) return Boolean is abstract;
procedure Accelerate(Self : Vehicle_Type) is abstract;
procedure Brake(Self : Vehicle_Type) is abstract;
private
type Vehicle_Type is abstract tagged null record;
end Vehicle;
Notice how the package has no body, it is a specification only and all operations are abstract, which means that any types which derive from this one must provide implementations of all the primitive operations.
Again, this can then be derived from to create a number of concrete vehicles:
Ada95 code
with Vehicle;
package Car is
type Car_Type is new Vehicle.Vehicle_Type with private;
function Gear_Up(Self : Car_Type) return Boolean;
function Gear_Down(Self : Car_Type) return Boolean;
procedure Accelerate(Self : Car_Type);
procedure Brake(Self : Car_Type);
private
type Car_Type is new Vehicle.Vehicle_Type with
null record;
end Car;
package body Car is
function Gear_Up(Self : Car_Type) return Boolean is
begin
-- Change the car's gears.
end Gear_Up;
-- Etc.
end Car;
with Vehicle;
package Van is
type Van_Type is new Vehicle.Vehicle_Type with private;
function Gear_Up(Self : Van_Type) return Boolean;
function Gear_Down(Self : Van_Type) return Boolean;
procedure Accelerate(Self : Van_Type);
procedure Brake(Self : Van_Type);
private
type Van_Type is new Vehicle.Vehicle_Type with
null record;
end Van;
package body Van is
function Gear_Up(Self : Van_Type) return Boolean is
begin
-- Change the van's gears.
end Gear_Up;
-- Etc.
end Van;
with Vehicle;
package Scooter is
type Scooter_Type is new Vehicle.Vehicle_Type with
private;
function Gear_Up(Self : Scooter_Type) return Boolean;
function Gear_Down(Self : Scooter_Type) return Boolean;
procedure Accelerate(Self : Scooter_Type);
procedure Brake(Self : Scooter_Type);
private
type Scooter_Type is new Vehicle.Vehicle_Type with
null record;
end Scooter;
package body Scooter is
function Gear_Up(Self : Scooter_Type) return Boolean is
begin
-- Change the scooter's gears.
end Gear_Up;
-- Etc.
end Scooter;
So, where ever a pointer to a Vehicle type is used it is possible to assign either Car, Van or Scooter instance to that variable:
Ada95 code
with Vehicle;
with Car;
with Scooter;
with Van;
procedure Test is
-- Make sure we can accept pointers to all vehicles
-- in this class.
type Vehicle_Access is access all
Vehicle.Vehicle_Type'Class;
A : Vehicle_Access;
C : aliased Car.Car_Type;
S : aliased Scooter.Scooter_Type;
V : aliased Van.Van_Type;
Result : Boolean;
begin
-- Call's Car.Gear_Up
A := C'Access;
Result := Vehicle.Gear_Up(A.all);
-- Call's Scooter.Gear_Up
A := S'Access;
Result := Vehicle.Gear_Up(A.all);
-- Call's Van.Gear_Up
A := V'Access;
Result := Vehicle.Gear_Up(A.all);
end Test;
I have placed a full example into a compressed text file which can be built with GNAT using the following commands:
Bash code
$ gunzip abstract_types.ada.gz
$ gnatchop -cw abstract_types.ada
$ gnatmake test.adb
Other Ada95 compilers will differ.
Download abstract_types.ada.gz
Reply #1 on : Fri September 14, 2007, 22:51:10
Write a comment
- Required fields are marked with *.

Reply #2 on : Sat September 22, 2007, 16:19:45