5

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"

4

3 回答 3

7

需要注意的关键是“接口类型的所有用户定义的原始子程序都应该是抽象子程序或空过程”。(参考)即您不能定义将接口本身作为参数的子程序(是的,我知道这与 Java 不同。)这就是您在 TestVehicles 声明中收到错误的原因。

本质上,您必须定义一个实现接口的类型,然后使用该类型。

关于接口的 Ada Rationale 章节详细讨论了这一点。

这是一个基于您的问题的工作示例-我重命名了一些内容并修复了一些错误,这些错误可能在您看到的错误消息中丢失:-) 请注意添加了一个实例化车辆接口的类型“Concrete_Vehicles”。

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;

编译和运行:

[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!
于 2013-05-05T14:28:07.863 回答
5

Java 风格的接口是在 Ada2005 中引入的:

type Vehicle is interface;

接口上的任何操作都必须是抽象的:

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

继承接口时,必须将其指定为父接口,并实现为接口定义的操作(“覆盖”告诉编译器父接口必须有相应的“开始”。关键字是可选的,但是):

type Tractor is new Vehicle with null record;

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

我将把剩下的留作练习,您可以在wikibook中阅读有关接口的更多信息

于 2013-05-04T19:15:57.273 回答
0

下面是您的程序的工作版本,使用指针(在 Ada 中称为“访问”)。您不需要接口的实现来使用接口,就像在 Java 示例中一样,这是面向对象编程和多态性的要点。

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:我是 Ada 的新手,我可能对某些事情有误,但我从https://github.com/raph-amiard/ada-synth-lib得到了这个概念被大量使用的想法。

于 2017-09-09T14:47:43.420 回答