我正在尝试编写一个通用包,其中一个操作是校验通过总线接收的数据记录.记录类型会有所不同,它是一个通用参数.但是,任何访问泛型参数成员的尝试都会导致编译错误.
错误......(Ada 95 GNAT 2009)
file.adb:XX no selector "Data" for private type "The_Transfer_Type" defined at file.ads:YY
Run Code Online (Sandbox Code Playgroud)
声明......
generic
type The_Transfer_Type is private;
SIZE : Integer;
package CC_Test_Channel is
function Checksum(Msg : The_Transfer_Type) return Integer;
end package
Run Code Online (Sandbox Code Playgroud)
身体......
function Checksum(Msg : The_Transfer_Type) return Integer is
Sum : Integer := 0;
begin
-- calculate the checksum
for i in 1 .. SIZE loop
Sum := Sum + Integer(Msg.Data(i));
end loop;
return Sum;
end Checksum;
Run Code Online (Sandbox Code Playgroud)
当您指定泛型参数是私有类型时,Ada假设您的意思是:-)
即你无法访问其组件.Ada不是" 鸭子类型 ",所以你是否知道实例化类型实际上可能拥有特定字段是无关紧要的.(如果使用Integer实例化The_Transfer_Type参数,您期望Checksum函数如何工作?)
解决此问题的一种方法是还提供访问器函数作为通用的参数,该参数将检索在这种情况下计算校验和所需的数据.例如:
generic
type The_Transfer_Type is private;
with function Get_Checksummable_Data_Item
(Msg : The_Transfer_Type;
I : Integer) return Integer;
SIZE : Integer;
package CC_Test_Channel is
function Checksum(Msg : The_Transfer_Type) return Integer;
end CC_Test_Channel;
Run Code Online (Sandbox Code Playgroud)
然后身体是:
function Checksum(Msg : The_Transfer_Type) return Integer is
Sum : Integer := 0;
begin
-- calculate the checksum
for i in 1 .. SIZE loop
Sum := Sum + Get_Checksummable_Data(Msg, I);
end loop;
return Sum;
end Checksum;
Run Code Online (Sandbox Code Playgroud)
您为Get_Checksummable_Data提供的函数特定于The_Transfer_Type,只是从The_Transfer_Type的组件字段返回所选值.
还有许多其他方法可以设置它,比如提供一个无约束的数组类型作为通用的形式参数和一个用于检索它的形式函数 - 这允许你也摆脱显式的SIZE形式参数.或者您可以将Checksum()函数编写为您使用实例化CC_Test_Channel的类型上的操作之一,然后具有:
with function Calculate_Checksum(Msg : The_Transfer_Type) return Integer;
Run Code Online (Sandbox Code Playgroud)
作为通用形式之一.
退一步,考虑一下可能性......