我想使用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 回答
我所知道的唯一一个如下所述,可能不是规范的 . 这不是严格的接口继承,但它可以让你朝着正确的方向 . 它需要使用判别式标记记录 .
诀窍是定义2个标记类型 . 一个是经典类定义,另一个是“接口”继承 .
然后,您可以使用判别式操作一个对象,该对象可以访问接口 Contract 和类 Contract . 在同一个包中声明两者应该可以让您完全了解私有部分,并进行确认 .
简而言之 :
Trick对象实现了您的InterfaceX Contract .
您必须为ClassA对象或Trick对象定义instantiaton / accessors . 我认为类型也应该是有限的 .
我总是听到人们称之为“罗森诡计”,猜测它是以J.-P.命名的 . 罗森 .
也许你会在这里找到一些更精确的答案http://www.adaic.org/resources/add_content/standards/95rat/rat95html/rat95-p2-4.html#6
Ada 95中的接口是
abstract tagged null record
: