[英]Ada aspects which are private to a package
假设我有世界上最愚蠢的环形缓冲区。
size: constant := 16;
subtype T is integer;
package RingBuffer is
procedure Push(value: T);
function Pop return T;
end;
package body RingBuffer is
buffer: array(0..size) of T;
readptr: integer := 0;
writeptr: integer := 1;
procedure Push(value: T) begin
buffer(writeptr) := value;
writeptr := (writeptr + 1) mod size;
end;
function Pop return T
begin
readptr := (readptr + 1) mod size;
return buffer(readptr);
end;
end;
因为我的代码很烂,所以我想添加前置条件和后置条件,以确保不会误用此条件。 因此,我将Push的实现更改如下:
procedure Push(value: T) with
pre => readptr /= writeptr
is begin
buffer(writeptr) := value;
writeptr := (writeptr + 1) mod size;
end;
但是,出现编译错误,因为我需要将方面定义放在过程的声明中,而不是在实现中。
问题是,这是一个包装。 我的声明是公开的。 前提条件所依赖的值属于程序包主体,声明不可见。 为了将方面定义放入声明中,我将必须重构代码以将实现细节公开到包的公共部分(在本例中为readptr
和writeptr
)。 我不想那样做。
我可以想到一些解决方法,例如让我的Push()
调用仅在具有先决条件的主体中定义的私有PushImpl()
过程,但这太可怕了。 什么是正确的方法?
我认为,当验证检查是私有的时,这总是一个问题,而解决方案是声明一个函数来执行检查:
package RingBuffer is
function Is_Full return Boolean;
procedure Push(value: T) with Pre => not Is_Full;
function Pop return T;
(无论如何, Is_Full
可能很有用;在其他情况下,可能并非如此)。
如果将实现保留在程序包主体中,则也需要将Is_Full
放在那里,但是您可以将它们移至规范并使用表达式函数:
package RingBuffer is
function Is_Full return Boolean;
procedure Push(value: T) with Pre => not Is_Full;
function Pop return T;
private
buffer: array(0..size) of T;
readptr: integer := 0;
writeptr: integer := 1;
function Is_Full return Boolean is (Readptr = Writeptr);
end RingBuffer;
合同方面旨在在(子)类型和子程序的公共视图中使用。
如果要将检查保留在私有视图中,那么将其编写为子程序中的第一条语句很简单:
begin
if Is_Full then
raise Constraint_Error with "Ring buffer is full.";
end if;
...
一些不请自来的建议:
Is_Empty
检查。 type Indexes is mod 16;
Index type Indexes is mod 16;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.