首页 文章

实现类似于Ada 95界面的最佳方法是什么?

提问于
浏览
0

我想使用Ada 95实现类似于接口的东西(因此典型的OO接口不可用) . 我通过在记录中使用泛型和一组“指向方法”来完成它 . 代码如下 .

EDIT: 我知道可以通过将子程序作为形式参数传递给泛型包来完成,但我想避免向它传递太多参数 .

我认为必须有更好的方法来实现我想要的东西,所以我想如果我是对的,如果是的话,我想看一个代码的例子 .

"interface"在名为 Drivers 的通用包中声明 . 在那里,有一条记录,其中包含表示驱动程序的泛型类型的变量和包含其操作的记录:

drivers.ads

generic 
    type T is private;
    type Error is private;
    NOT_IMPLEMENTED_CODE : Error;

package Drivers is

    type Driver is private;

    -- Need to declare these types because I compile with Ada 95.
    type ToStringPtr is access function(self : in T) return String;
    type ReadLinePtr is access procedure(self : in T; buffer : out String; err : out Error);

    type DriverOps is
    record
        to_string_op : ToStringPtr := null;
        read_line_op : ReadLinePtr := null;
    end record;

    function create_driver(underlying : T; ops : DriverOps) return Driver;

    function to_string(self : in Driver) return String;

    procedure read_line(self : in Driver; buffer : out String; err : out Error);


    private
        type Driver is
        record
            underlying : T;
            ops : DriverOps;
        end record;

end Drivers;

drivers.adb

package body Drivers is

    function create_driver(underlying : T; ops : DriverOps) return Driver is
    begin
        return (underlying, ops);
    end create_driver;

    function to_string(self : in Driver) return String is
    begin
        if self.ops.to_string_op /= null then
            return self.ops.to_string_op(self.underlying);
        else
            return "";
        end if;
    end to_string;

    procedure read_line(self : in Driver; buffer : out String; err : out Error) is
    begin
        if self.ops.read_line_op /= null then
            self.ops.read_line_op(self.underlying, buffer, err);
        else
            err := NOT_IMPLEMENTED_CODE;
        end if;
    end read_line;

end Drivers;

main.adb

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Fixed; 

with Drivers;

procedure main is

    type Error is (SUCCESS, NOT_IMPLEMENTED, UNKNOWN);

    type MyInt is new Integer;

    function to_string(self : in MyInt) return String is
    begin
        return Integer'Image( Integer(self) ); --'
    end to_string;

    procedure read_line(self : in MyInt; buffer : out String; err : out Error) is
    begin
        Ada.Strings.Fixed.Move(
            Target => buffer,
            Source => "Lets suppose we have read this from a device" & ASCII.LF,
            Pad => ASCII.NUL); 
        err := SUCCESS;
    end read_line;


    package IntDrivers is new Drivers(MyInt, Error, NOT_IMPLEMENTED);
    use IntDrivers;


    underlying : MyInt := 25;

    int_driver_ops : DriverOps := (
        to_string_op => to_string'access, --'
        read_line_op => read_line'access  --'
    );

    my_driver : Driver := create_driver(underlying, int_driver_ops);
    buffer : String(1..256) := (others => Character'Val(0)); --'
    err : Error := SUCCESS;
begin
    Put_Line(to_string(my_driver));

    read_line(my_driver, buffer, err);
    Put(buffer);
    Put_Line(Error'Image(err)); --'
end main;

2 回答

  • 4

    我所知道的唯一一个如下所述,可能不是规范的 . 这不是严格的接口继承,但它可以让你朝着正确的方向 . 它需要使用判别式标记记录 .

    诀窍是定义2个标记类型 . 一个是经典类定义,另一个是“接口”继承 .

    然后,您可以使用判别式操作一个对象,该对象可以访问接口 Contract 和类 Contract . 在同一个包中声明两者应该可以让您完全了解私有部分,并进行确认 .

    简而言之 :

    type InterfaceX is abstract ....; -- abstract class and services
    
    type ClassA is tagged ...; -- or is new ....
    type Trick (component : ClassA) is new InterfaceX ...; -- this type gives you access to classA and interfaceX primitives
    

    Trick对象实现了您的InterfaceX Contract .

    您必须为ClassA对象或Trick对象定义instantiaton / accessors . 我认为类型也应该是有限的 .

    我总是听到人们称之为“罗森诡计”,猜测它是以J.-P.命名的 . 罗森 .

    也许你会在这里找到一些更精确的答案http://www.adaic.org/resources/add_content/standards/95rat/rat95html/rat95-p2-4.html#6

  • 5

    Ada 95中的接口是 abstract tagged null record

    package Abstract_Driver is
    
       type Instance is abstract tagged null record;
       subtype Class is Instance'Class; --' (defect syntax highlighter)
    
       function Image (Item : in Instance) return String is abstract;
    
       procedure Read_Line (Item   : in out Instance;
                            Buffer :    out String) is abstract;
    
    end Abstract_Driver;
    
    with Abstract_Driver;
    
    package Text_IO_Driver is
    
       subtype Parent is Abstract_Driver.Instance;
       type Instance is new Parent with private;
       subtype Class is Instance'Class; --' (defect syntax highlighter)
    
       function Image (Item : in Instance) return String;
    
       Buffer_Too_Small : exception;
    
       procedure Read_Line (Item   : in out Instance;
                            Buffer :    out String);
    
    private
    
       type Instance is new Parent with null record;
    
    end Text_IO_Driver;
    
    with Ada.Text_IO;
    
    package body Text_IO_Driver is
    
       function Image (Item : in Instance) return String is
       begin
          return "Ada.Text_IO.Standard_Input";
       end Image;
    
       procedure Read_Line (Item   : in out Instance;
                            Buffer :    out String) is
          Last : Natural;
       begin
          Buffer := (Buffer'Range => ' '); --' (defect syntax highlighter)
          Ada.Text_IO.Get_Line (Item => Buffer,
                                Last => Last);
          if Last = Buffer'Last then --' (defect syntax highlighter)
             raise Buffer_Too_Small;
          end if;
       end Read_Line;
    
    end Text_IO_Driver;
    

相关问题