2014-03-03 102 views
0

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

作为一个简单的例子,我想要一个Long_Integer字段,但外部世界应该只能够将其设置为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; 

一个。广告

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:3​​9:在选定的组件无效前缀 “X”

你看,为什么?

+1

将'C'声明为'C类型标记为private;'。 'Object.procedure(...)'或'Object.function(...)'符号只有在对象被标记时才被允许,并且从'test.adb'中的那个点只能看到'type C是私有的; ',不允许知道“C”类型被标记。 – ajb

+0

谢谢你们两位:-) – user1091344

+0

@ajb,@'Brian Drummond':还有一个问题:-) C_Access类型,这是正确的还是我应该将它移入私有部分? – user1091344

回答

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; 

NB这点符号X.c是艾达 - 2012分之2005语法。 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)我的错:我应该指出这个对象。子程序的前缀表示法适用于标记类型;在包规范A中向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
值为123

+0

嗨,谢谢。我添加了一个例子,该例子在当时不起作用。你知道为什么吗? – user1091344

+0

@ajb:谢谢 - 编辑。 –

+0

谢谢你们两位:-) – user1091344