Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement interface in Ada?

Tags:

oop

interface

ada

Dont know what this oop pattern is called but how can I do the same pattern in Ada? For example this code:

interface Vehicle{
    string function start();
}

class Tractor implements Vehicle{
    string function start(){
        return "Tractor starting";
    }
}
class Car implements Vehicle{
    string function start(){
        return "Car  starting";
    }
}

class TestVehicle{
    function TestVehicle(Vehicle vehicle){
        print( vehicle.start() );
    }
}
new TestVehicle(new Tractor);
new TestVehicle(new Car);

my failed attempt in Ada: How to fix it properly?

with Ada.Text_IO;

procedure Main is

   package packageVehicle is
      type Vehicle is interface;
      function Start(Self : Vehicle) return String is abstract;
   end packageVehicle;

   type Tractor is new packageVehicle.Vehicle with null record;
   overriding -- optional
   function Start(Self : Tractor) return string is
   begin
      return "Tractor starting!";
   end Start;
   type Car is new packageVehicle.Vehicle with null record;
   overriding -- optional
   function Start(Self : Car) return string is
   begin
      return "Car starting!";
   end Start;


   procedure TestVehicle(Vehicle : packageVehicle.Vehicle) is
   begin
      Ada.Text_IO.Put_Line( "Testing a vehicle" );
      Ada.Text_IO.Put_Line( Start(Vehicle) );
   end;

   Tractor0 : Tractor;
   Car0 : Car;

begin

   Ada.Text_IO.Put_Line( TestVehicle(Tractor0) );
   Ada.Text_IO.Put_Line( TestVehicle(Car0) );

end Main;

Compiler says: Builder results warning: declaration of "TestVehicle" is too late Builder results warning: spec should appear immediately after declaration of "Vehicle"

like image 411
Jossi Avatar asked May 04 '13 17:05

Jossi


2 Answers

The key thing to be aware of is "All user-defined primitive subprograms of an interface type shall be abstract subprograms or null procedures." (Ref) I.e. you can't define a subprogram that takes the interface itself as a parameter (yes, I know this is different from Java.) This is why you're getting the error on the TestVehicles declaration.

Essentially, you have to define a type that implements the interface(s), then work with that type.

The Ada Rationale chapter on Interfaces discusses this in some detail.

Here's a working example based on your question--I renamed some things and fixed a couple errors that were probably getting lost amongst the error messages you were seeing :-) Note the addition of a type 'Concrete_Vehicles' that instantiates the Vehicle interface.

with Ada.Text_IO; use Ada.Text_IO;

procedure Interface_Test is

   package Package_Vehicle is 
      type Vehicle is interface;

      function Start(Self : Vehicle) return String is abstract;
   end Package_Vehicle;


   type Concrete_Vehicles is abstract new Package_Vehicle.Vehicle with null record;


   type Tractor is new Concrete_Vehicles with null record;

   overriding -- optional
   function Start(Self : Tractor) return string is
   begin
      return "Tractor starting!";
   end Start;

   type Car is new Concrete_Vehicles with null record;
   overriding -- optional
   function Start(Self : Car) return string is
   begin
      return "Car starting!";
   end Start;


   procedure TestVehicle(Vehicle : Concrete_Vehicles'Class) is
   begin
      Ada.Text_IO.Put_Line( "Testing a vehicle" );
      Ada.Text_IO.Put_Line( Start(Vehicle) );
   end;

   Tractor0 : Tractor;
   Car0 : Car;

begin

  TestVehicle(Tractor0);
  TestVehicle(Car0);

end Interface_Test;

Compiling and running:

[22] Marc say: gnatmake interface_test.adb
gcc -c interface_test.adb
gnatbind -x interface_test.ali
gnatlink interface_test.ali
[23] Marc say: ./interface_test
Testing a vehicle
Tractor starting!
Testing a vehicle
Car starting!
like image 118
Marc C Avatar answered Nov 05 '22 08:11

Marc C


Java-style interfaces was introduced in Ada2005:

type Vehicle is interface;

Any operations on the interface must be abstract:

function start(Self : Vehicle) return String is abstract;

When inheriting the interface, you must specify it as a parent, and implement the operations defined for the interface ("overriding" tells the compiler that the parent must have a corresponding "start". The keyword is optional, however):

type Tractor is new Vehicle with null record;

overriding -- optional
function start(Self : Tractor) return String;

I will leave the rest as an exercise, you can read more about interfaces in the wikibook

like image 31
egilhh Avatar answered Nov 05 '22 08:11

egilhh