Jossi
Jossi

Reputation: 1080

How to implement interface in 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"

Upvotes: 5

Views: 4764

Answers (3)

Frank Buss
Frank Buss

Reputation: 722

Below is a working version of your program, using pointers (called "access" in Ada). You don't need an implementation of the interface to work with the interface, same as in your Java example, which is the main point of object oriented programming and polymorphism.

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 : Access packageVehicle.Vehicle'class) is
begin
    Ada.Text_IO.Put_Line( "Testing a vehicle" );
    Ada.Text_IO.Put_Line( Vehicle.Start );
end;

Tractor0 : access Tractor'Class := new Tractor;
Car0 : access Car'Class := new Car;

begin

TestVehicle(Tractor0);
TestVehicle(Car0);

end Main;

PS: I'm new to Ada, I might be wrong with things, but I have the idea from https://github.com/raph-amiard/ada-synth-lib where this concept is used a lot.

Upvotes: 0

Marc C
Marc C

Reputation: 8522

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!

Upvotes: 6

egilhh
egilhh

Reputation: 6430

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

Upvotes: 5

Related Questions