Ada: управление частным типом

#ada

#ada

Вопрос:

Я вроде как новичок в Ada и недавно получил ошибку, которую, похоже, не знаю, как решить.

У меня есть следующий код:

data.ads

     with Text_IO; use text_io;
with ada.Integer_Text_IO; use ada.Integer_Text_IO;

package data is

type file is private;

   type file_set is array (Integer range <>) of file;
   procedure file_Print (T : in out file); --Not used

private
type file is record
      start, deadline : integer;
end record;

end data;
 

Main.adb

 with ada.Integer_Text_IO; use ada.Integer_Text_IO;


procedure Main is

   Num_files: integer:=3; 
  
   Files:file_set(1..Num_files);
     
begin
   
Files(1):=(2,10); -- Expected private type "file" defined at data.ads

for i in 1..Num_Files loop
      
      Put(integer'Image(i));
      New_Line;
      data.File_Print(Files(i));
 

Но я получаю эту ожидаемую ошибку частного типа «file», определенного в data.ads
Как я могу получить доступ к типу файла и объявить новый массив значений в main?

Комментарии:

1. Обратите внимание, что «доступ» имеет особое значение в Ada, поэтому его использование в названии несколько вводит в заблуждение. «Манипулировать» может быть лучшим выбором.

Ответ №1:

Это верно — вы не можете видеть или манипулировать тем, что находится внутри частного типа. Это нарушило бы инкапсуляцию. Следуют ошибки и угрозы безопасности.

Вы можете взаимодействовать с частным типом только с помощью его методов: функций и процедур, объявленных в пакете, в котором он объявлен.

Теперь file_set НЕ является частным типом (вы можете рассмотреть возможность сделать его закрытым позже, для лучшей инкапсуляции, но пока ….) вы можете проиндексировать его, чтобы получить доступ к файлу внутри него (используя одну из этих процедур).

 Files(1):=(2,10);
 

Поскольку вы хотите создать файл здесь, вам нужен метод для создания файла … немного похоже на конструктор в C , но на самом деле больше похоже на шаблон проектирования фабрики объектов. Добавьте это в пакет:

    function new_file(start, deadline : integer) return file;
 

И реализовать его в теле пакета:

 package body data is

    function new_file(start, deadline : integer) return file is
    begin
       -- check these values are valid so we can guarantee a proper file
       -- I have NO idea what start, deadline mean, so write your own checks!
       -- also there are better ways, using preconditions in Ada-2012
       -- without writing explicit checks, but this illustrates the idea
       if deadline < NOW or start < 0 then 
          raise Program_Error;
       end if;
       return (start => start, deadline => deadline);
    end new_file;

    procedure file_Print (T : in out file) is ...

end package body;
 

и это дает пользователям вашего пакета разрешение на запись

 Files(1):= new_file(2,10);
Files(2):= new_file(start => 3, deadline => 15);
 

но если они попытаются создать мусор, чтобы использовать вашу систему

 Files(3):= new_file(-99,-10);     -- Oh no you don't!
 

это ЕДИНСТВЕННЫЙ способ создать файл, чтобы они не могли обойти ваши проверки.

Комментарии:

1. «это ЕДИНСТВЕННЫЙ способ создать файл»: ну, нет. «Они» могут делать F : Data.File; , а затем использовать любые случайные значения, которые он получает по умолчанию. Чтобы избежать этого, вы должны сделать тип неопределенным, но тогда он не может быть компонентом массива; или предоставить недопустимые начальные значения по умолчанию, а затем проверять правильность при каждом использовании.