我想使用Ada 95实现类似于接口的内容(因此典型的OO接口不可用)。我通过在记录中使用泛型和一组“方法的指针”来完成此操作。代码如下。
编辑:我知道可以通过将子程序作为形式参数传递给泛型包来完成,但是我想避免向它传递太多参数。
我认为必须有一种更好的方法来实现我想要的东西,所以我想如果我是对的,如果是的话,我想看一个代码示例。
“接口”在称为Drivers
的通用包中声明。那里有一条记录,该记录包含一个表示驱动程序的通用类型的变量,并包含一个包含其操作的记录:
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;
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;
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;
答案 0 :(得分:5)
下面将描述我所知道的唯一一个,可能不是规范。这不是严格的接口继承,但可以使您朝正确的方向发展。 它要求使用区分标签的记录。
诀窍是定义2个标记类型。一个是您的经典类定义,另一个是“接口”继承。
然后,您可以操纵一个使用判别式访问接口协定和类协定的对象。在同一程序包中同时声明两者,可以使您完全了解私有部分。
简而言之:
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合同。
您将必须为ClassA对象或Trick对象定义实例化/访问器。我认为类型也应该受到限制。
我经常听到人们称其为“罗森把戏”,猜想它是以J.-P.罗森。
也许您会在http://www.adaic.org/resources/add_content/standards/95rat/rat95html/rat95-p2-4.html#6
中找到一些更准确的答案答案 1 :(得分:4)
接口是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;