Types 艾达:有没有一种合适的方式让两种类型的人;使用「;彼此受限于+;访问权限=can';不编译

Types 艾达:有没有一种合适的方式让两种类型的人;使用「;彼此受限于+;访问权限=can';不编译,types,reference,include,ada,Types,Reference,Include,Ada,我是Ada的新手,我在类型、引用和包含方面遇到了无尽的问题。 下面我有两种需要相互“使用”的类型:Train和Platform,我在下面包含了源代码 由于直接“withing”不起作用(我知道两种ada类型不能直接“看到”对方,或者会发生循环包含错误),我选择了一个通用包(也包括在下面),该包“限制了其他两种,并且还实现了访问类型,因此包含公共将使包能够使用指向训练和平台的指针 然而,这似乎也不是一个可行的解决方案:虽然我可以使用common中定义的ref类型声明变量,但我实际上无法访问它们上的

我是Ada的新手,我在类型、引用和包含方面遇到了无尽的问题。 下面我有两种需要相互“使用”的类型:
Train
Platform
,我在下面包含了源代码

由于直接“withing”不起作用(我知道两种ada类型不能直接“看到”对方,或者会发生循环包含错误),我选择了一个
通用
包(也包括在下面),该包“
限制了其他两种,并且还实现了访问类型,因此包含
公共
将使包能够使用指向
训练
平台的指针

然而,这似乎也不是一个可行的解决方案:虽然我可以使用
common
中定义的ref类型声明变量,但我实际上无法访问它们上的任何方法/条目。我在Railway-train.adb中强调了这条麻烦的线路,并发表了评论。当编译器到达该行时,它将停止并出现错误:

Invalid prefix in selected component "StopAtPlatform"
我知道Ada与其他语言非常不同,但作为一个来自C#的人,我真的很难理解为什么两种类型很难相互使用,以及为什么“指针”(访问类型)似乎不能正常工作。谁能解释我做错了什么

如果可以的话,请不要发表任何评论,比如“为什么你需要两种类型的人互相使用,这是一种糟糕的做法”。。。谢谢:)

资料来源如下:

铁路-train.ads

with Railway.Common; use Railway.Common;
with Ada.Text_IO; use Ada.Text_IO;

package Railway.Train is

   task type Train is
      entry Create(id : in Natural; capacity : in Positive; Route : Route_Array; me : Train_Ref);
   end Train;

end Railway.Train;
Railway-train.adb:

package body Railway.Train is

   task body Train is
      Myself : Train_Ref;
      Train_ID : Natural;
      Passenger_Load : Integer := 0;
      Passenger_Capacity : Positive;
      Train_Route : Route_Array;
   begin
      accept Create (id : in Natural; capacity : in Positive; Route : in Route_Array; me : Train_Ref) do
         Myself := me;
         Train_ID := id;
         Passenger_Capacity := capacity;
         Train_Route := Route;
      end Create;

      loop
         for i in Train_Route'Range loop
            Train_Route(i).StopAtPlatform(Myself); --ERROR OCCOURS HERE
         end loop;
      end loop;
   end Train;

end Railway.Train;
Railway-platform.ads:

with Railway.Common; use Railway.Common;

package Railway.Platform is

   protected type Platform is
      entry StopAtPlatform(Incoming_Train : in Train_Ref);
      procedure DepartFromPlatform;
   private
      Train_At_Platform : Train_Ref := null;
   end Platform;

end Railway.Platform;
railway-platform.adb:

package body Railway.Platform is

   protected body Platform is

      --Train occupies the platform. This stops the access to the platform by all other trains, until DepartFromPlatform is called
      entry StopAtPlatform(Incoming_Train : in Train_Ref) when Train_At_Platform = null is
      begin
         Train_At_Platform := Incoming_Train;
      end StopAtPlatform;

      --Train leaves the platform. This re-opens access to the platform by all other trains
      procedure DepartFromPlatform is
      begin
         Train_At_Platform := null;
      end DepartFromPlatform;

   end Platform;

end Railway.Platform;
最后,Railway-common.ads:

limited with Railway.Platform;
limited with Railway.Train;

package Railway.Common is

   --Common stuff
   type Train_Ref is access all Train.Train;
   type Platform_Ref is access all Platform.Platform;

   type Route_Range is range 1..100;
   type Route_Array is array (Route_Range) of Platform_Ref;

end Railway.Common;

编辑:正如ajb下面的回答所指出的那样,在Railway.Platform中添加
在Railway-train.adb上生成一个编译器错误:(

我认为正确的答案是您需要

with Railway.Platform;
上面的
包体Railway.Train;
。原因是
Railway.Common
的规范将
Route\u Array
定义为
Platform\u Ref
的数组,这是对有限视图类型的访问(因为
Railway.Common
表示
受Railway.Train
Platform
)受
限制的
无法提供有关
铁路.站台
中类型的详细信息,这就是为什么
车站站台
不可见的原因。将带有
的常规
添加到
铁路.Train
的正文会使该标识符可见。它不会创建循环依赖项,因为它位于正文上铁路列车的

然而,当我尝试使用GNAT时,结果是一个错误框。我假设你正在使用它,因为它在我使用
添加
之前给了我完全相同的错误消息。因此,虽然我认为这个答案是正确的,但在他们能够解决问题之前,它可能不会帮助你

我认为在Ada中这比在C#中更难的主要原因是Ada是一种较旧的语言,最初是为编译文件时编译器必须拥有所需的所有信息的范例而设计的。源文件引用了它尚未看到的标识符(因为它在一个尚未编译的源文件中)不会工作。我认为公平地说,当时可用的编译器技术还不存在


编辑:我的早期版本对程序的结构做了一些错误陈述。

一个解决方案是在同一个包中声明这两种类型。

我可以确认,我也得到了“GNAT bug”转储:(我可以使用其他编译器吗?或者我只是在AdaCore修复它之前被卡住了?@Master\T不幸的是,我试过的另一个编译器也失败了,原因完全不同。这很奇怪,因为它似乎没有这么复杂的代码,我不敢相信没有人写过类似的东西,遇到过这个错误……我们能确认一下吗rm这是一个编译器错误?而且,无论如何,要知道到底是什么触发了它?我试图从平台上删除所有对Train的引用,但这种情况仍然发生,所以我认为这不是由两个包相互使用引起的…@Master\u不确定您的问题的意思…如果编译器输出显示“检测到了GNAT bug”然后我认为这证实了存在编译器错误。虽然您的代码看起来并不复杂,但有时组合使用某些功能(
受限于两个包、任务和受保护类型上的
)会导致意外问题,因为并非所有可能的组合都可以测试。这就是我的意思“这真的是一个编译器错误吗”,即:可能我正在做的事情实际上是语言禁止的,但它没有经过开发人员的正确测试,并显示为一个编译器错误,而实际上是我做错了什么…不幸的是,编译器消息没有给出任何关于到底是什么语句导致了问题的信息。。。