一般问题:是否可以覆盖记录字段?
作为一个简单的例子,我希望有一个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”中的前缀无效
你知道吗,为什么?
答案 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