在以下代码中,Mix_Card_Reader继承自Mix_IO_Device,后者是抽象的标记记录。
以前它包含一个Positive
和两个Stream_Access
成员。我想更改代码,使其改为使用File_Type
成员。
原因是我希望这种类型的每个实例都能够在需要时打开和关闭其文件,或者在需要时完全不打开。
问题是我无法初始化此继承类型,因为File_Type
是受限类型。如何编写我的Create_Mix_Card_Reader
函数以允许这样做?
。ads ...
type Mix_IO_Device is abstract tagged limited
record
Block_Size : Positive;
Input_File : File_Type;
Output_File : File_Type;
end record;
type Mix_Card_Reader is new Mix_IO_Device with null record;
。adb ...
function Create_Mix_Card_Reader return Mix_IO_Device_Access is
Ret : Mix_IO_Device_Access := new Mix_Card_Reader'(16, null, null);
begin
return Ret;
end Create_Mix_Card_Reader;
[GNAT抱怨我不能将null, null
传递给这对File_Type
成员,因为它们当然不兼容,空值是以前曾经拥有Stream_Access
成员时的剩余值。似乎我必须在这里传递一些信息,但是我不想过早地打开文件只是为了使编译器满意。
该怎么办?
编辑:我有几个明显的选择:
access File_Type
(但我仍然必须在其他位置保持文件的打开/关闭)。这应该可以解决问题:
function Create_Mix_Card_Reader return Mix_IO_Device_Access is
Ret : Mix_IO_Device_Access := new Mix_Card_Reader'(
16, Input_Type => <>, Ouptut_Type => <>);
begin
return Ret;
end Create_Mix_Card_Reader;
框符号是默认值的占位符。您至少需要Ada 2005才能在聚合中使用它,并且不得使用位置表示法,有关详细信息,请参见Ada 2005 Rationale。如果需要,可以将两个分配缩短为others => <>
。
您实际上不需要初始化File_Type
变量,因为它们从初始化(但未打开)开始。
我给您的印象是您不是从使用访问类型开始的?试试这个(不是所提出问题的答案,但可能仍然有用):
with Ada.Text_IO; use Ada.Text_IO;
package Wossname is
type Mix_IO_Device is abstract tagged limited
record
Block_Size : Positive;
Input_File : File_Type;
Output_File : File_Type;
end record;
type Mix_Card_Reader is new Mix_IO_Device with null record;
function Create_Mix_Card_Reader return Mix_IO_Device'Class;
end Wossname;
我不确定这里的确切合法性,但我认为这是“就地初始化”:
package body Wossname is
function Create_Mix_Card_Reader return Mix_IO_Device'Class is
begin
return Ret : Mix_Card_Reader do
Ret.Block_Size := 16;
end return;
end Create_Mix_Card_Reader;
end Wossname;
您可以看到它可以编译(并运行!)好。
procedure Wossname.Test is
Reader : Mix_IO_Device'Class := Create_Mix_Card_Reader;
begin
begin
Create (Reader.Output_File, Name => "wossname.out", Mode => Out_File);
exception
when Use_Error =>
Open (Reader.Output_File, Name => "wossname.out", Mode => Out_File);
end;
Put (Reader.Output_File, "hi!");
Close (Reader.Output_File);
end Wossname.Test;