【问题标题】:How to implement interface in Ada?如何在 Ada 中实现接口?
【发布时间】:2013-05-04 17:23:38
【问题描述】:

不知道这个 oop 模式叫什么,但我怎样才能在 Ada 中做同样的模式? 例如这段代码:

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);

我在 Ada 中的失败尝试: 如何正确修复?

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;

编译器说: 生成器结果警告:“TestVehicle”的声明为时已晚 生成器结果警告:规范应在“车辆”声明后立即出现

【问题讨论】:

  • 我不确定接口,但我知道动态调度基础/父包需要在单独的包文件中。

标签: oop interface ada


【解决方案1】:

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

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

Interfaces 上的 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!

【讨论】:

    【解决方案2】:

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

    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阅读更多关于接口的内容

    【讨论】:

    • 这是我尝试过的,但我不知道如何使它工作:
    • 你希望 TestVehicle 过程可以接收各种车辆,而不仅仅是 packageVehicle.Vehicle,所以添加 'class: procedure TestVehicle(Vehicle : packageVehicle.Vehicle'class) is
    • 您还需要了解您正在调用的启动函数:Ada.Text_IO.Put_Line( packageVehicle.Start(Vehicle) ); 或使用点分符号 (Ada2005):Ada.Text_IO.Put_Line( Vehicle.Start ); 此外,TestVehicle 不返回字符串,因此您不会需要主体中的 put_lines。
    【解决方案3】:

    下面是您的程序的工作版本,使用指针(在 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 得到了这个概念被大量使用的想法。

    【讨论】:

      猜你喜欢
      • 2022-07-12
      • 1970-01-01
      • 2022-03-13
      • 2020-04-30
      • 2010-10-16
      • 2011-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多