我正在尝试编译此代码:
function valid(a:Toto'Class; t: Titi) return Boolean with Pre'Class => fonction(a);
GNAT说“aspect”pre'class“只能为标记私有的原始操作指定”
我想这是因为Toto'Class,但我怎么能让它起作用?
答案 0 :(得分:3)
我认为Pre'Class
和Post'Class
的目的是指定即使子程序被覆盖也适用的前提条件。
package Pack1 is
type Base_Type is tagged record ... end record;
procedure Operation (Obj : Base_Type) with Pre'Class => [condition];
end Pack1;
这意味着如果满足条件,则允许Operation
,即使派生类型强加了其他条件。假设一个过程在Base_Type'Class
对象上使用此操作:
procedure Something_Else (Obj : Base_Type'Class) is
begin
-- check to make sure the condition is true
Obj.Operation;
end Something_Else;
Something_Else
不知道Obj
的实际类型是什么。但仍可以确保,如果Pre'Class
条件为true
,则可以执行Operation
(即,它满足前提条件)。如果条件只是Pre => [condition]
,则无法保证这会起作用,因为Obj
的实际类型可能是派生类型,并且可以为该派生类型覆盖Operation
具有更严格的条件,并且覆盖Operation
上的条件将是被检查的条件(因为调用将分派到覆盖的Operation
)。使用Pre'Class
时,将检查两个条件,并且如果任一条件为真,则操作是允许的(因此派生类型可以减少限制)。但重要的是,Something_Else
依赖合同,如果Pre'Class
条件为真,那么Operation
是允许的。
但是,如果Operation
无法覆盖,则无论如何都不重要。在您的示例中,由于Valid
的参数为Toto'Class
,并且由于(我假设)Titi
不是标记类型,因此Valid
不是基本操作,因此不是调度操作。
procedure Another_Procedure (Obj : Toto'Class; T : Titi) is
begin
if Obj.Valid(T) then
...
end if;
end Another_Procedure;
当Another_Procedure
调用Valid
时,它会始终调用您编写的Valid
;无论Valid
实际上是什么类型,它都不会发送到不同的Obj
。 Valid
不是调度功能。因此,在它上面放置一个类范围的前提条件是没有意义的。所以语言不允许它。
注意:在只有基本类型和派生类型而不是类型链的简单情况下,Pre'Class
表示如果条件<可以执行操作strong>或派生类型的任何前提条件都成功。 Post'Class
表示如果条件和派生类型的任何后置条件成功,则子程序符合条件。