覆盖记录字段

时间:2014-03-03 12:54:47

标签: record ada

一般问题:是否可以覆盖记录字段?

作为一个简单的例子,我希望有一个Long_Integer字段,但外部世界应该只能将它设置为整数。

package A is
   type B is record // edit: should be tagged to be able to use my intention below
      c : Long_Integer;
   end record;
end A;

X : B;

我可以通过使用以下函数/程序伪造我的意图:

function d (Object : B) return Integer is (Integer (Object.c));
procedure d (Object : B; Value : Integer) is
begin
   Object.c := Long_Integer (Value);
end d;

因此,我可以使用X.d获取值,使用X.d()来设置值。

但是,是否可以使用给定的函数和过程覆盖字段“c”并且更有趣,我可以覆盖它,以便我可以使用Xc:= Integer(3)来设置字段的值吗?


修改

test.adb

with Ada.Text_IO;
with A;

procedure Test is
   use A;

   X : C;
begin
   X.d (123);
   Ada.Text_IO.Put_Line("Value is " & X.d'Img);
end Test;

a.adb

package body A is

   function d (Object : C) return Integer is (Integer (Object.d));
   procedure d (Object : in out C; Value : Integer) is
   begin
      Object.d := Long_Integer (Value);
   end d;

end A;

a.ads

package A is

   type B is tagged private;
   type C is tagged private; -- tagged missed
   type C_Access is access all C; <-- is this line correct?

   function d (Object : C) return Integer;
   procedure d (Object : in out C; Value : Integer);

private

   type B is tagged null record;

   type C is new B with record
      d : Long_Integer;
   end record;

end A;

编译说:    test.adb:9:04:所选组件“X”中的前缀无效    test.adb:10:39:所选组件“X”中的前缀无效

你知道吗,为什么?

1 个答案:

答案 0 :(得分:4)

我可能会误解你的问题,但据我所知,你希望记录的外部视图看起来像一件事,而内部细节则完全不同。

再往前走一点,完全隐藏内部表示。

package A is
   type B is tagged private;

   function c (Object : B) return Integer;
   procedure c (Object : B; Value : Integer);
   -- set_c is probably a better name!

private
-- the "private" part allows other code to allocate B 
-- without seeing the implementation (package body)

   type B is tagged record     
      c : Long_Integer;
   end record;

end A;

包体很容易编写,这里没有显示:它包含了访问器的实现,或多或少都是你编写的。

然后你可以使用这个包:

with Ada.Text_IO;
with A;     -- assuming A is a separate pair of files, a.ads, a.adb.
            -- Unnecessary if A is a package in the current file.
use A;

procedure test is
   X : B;
begin
   X.c(123);  -- set value. 
   put_line("Value is " & integer'image(X.c));
end test;

注意,这个点符号X.c是Ada-2005/2012语法。 Ada-95需要c(X)......这仍然有效,意思相同。

每个包也是一个命名空间,因此您可以明确地编写

而不是use A;
procedure test is
   X : A.B;
begin
   X.c(123);  -- set value
   put_line("Value is " & integer'image(X.c));
end test;

编辑:实际上尝试你的工作示例而不是回答(!):

(1)我的错误:我应该指出子程序的object.prefix符号适用于标记类型;在程序包规范中为C的声明添加“tagged”可以解决这个问题。

type C is tagged private;

(2)函数d不能只重命名类型转换;将其包装为

   function d (Object : C) return Integer is 
   begin
      return Integer (Object.d);
   end d;

  

gnatmake测试
  gnatlink:警告:可执行文件名“test”可能与shell命令发生冲突   ./test
  价值是123