2014-03-03 117 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