在不使用判别式的情况下在Ada中导出记录类型时分配值

时间:2018-06-25 10:17:56

标签: struct ada derived-types

我正在尝试在Ada中建模三个实体:PersonWomanMan。我希望Person有一个字段Gender,对于Unknown,必须为Person;对于Male和{{1},必须是Man } Female

我想将WomanMan实现为Woman字段分别为PersonGender的{​​{1}}派生类型。

此外,我希望Male Female的唯一允许值为Person's,同样,Gender的{​​{1}}和Unknown Male

我尝试了以下方法,但是当然不能编译:

Man

我不想将Female声明为参数类型,因为这样可以将Woman设为package Persons is type Genders is (Male, Female, Unknown); type Person is private; type Man is private; type Woman is private; function Get_Age (Self : Person) return Integer; function Get_Name (Self : Person) return String; function Get_Weight (Self : Person) return Float; function Get_Height (Self : Person) return Float; function Get_gender (Self : Person) return Genders; private type Person is record Age : Integer := 0; Name : String (1..256) := (others => Character'Val(0)); -- ' Height, Weight : Float := 0.0; Gender : Genders := Unknown; end record; type Man is new Person with Gender => Male; type Woman is new Person with Gender => Female; end Persons; Person或{{1 }},而且我也不允许这样做。

可以做我想做的事吗?

3 个答案:

答案 0 :(得分:1)

我知道您说没有区别,但是您给出的理由是为了防止它们之间的分配。您是否愿意考虑将判别式隐藏在私人类型的后面?这样可以防止客户端代码进行分配,如果您使用类型派生,则可以防止您在软件包的内部代码中意外分配它们。下面是两个不同的示例,您可以在其中隐藏判别式以防止分配。编辑:使用泛型添加了第三个选项。

procedure jdoodle is

    package Persons1 is

       type Genders is (Male, Female, Unknown);

       type Person is private;
       type Man is private;
       type Woman is private;

    private

       type Implementation(Gender : Genders) is
          record
             Age            : Integer := 0;
             Name           : String (1..256) := (others => Character'Val(0)); -- '
             Height, Weight : Float := 0.0;
          end record;

       type Person is new Implementation(Unknown);
       type Man    is new Implementation(Male);         
       type Woman  is new Implementation(Female);

    end Persons1;

    package Persons2 is

       type Genders is (Male, Female, Unknown);

       type Person is private;
       type Man is private;
       type Woman is private;

    private

       type Person(Gender : Genders := Unknown) is
          record
             Age            : Integer := 0;
             Name           : String (1..256) := (others => Character'Val(0)); -- '
             Height, Weight : Float := 0.0;
          end record;

       type Man    is new Person(Male);         
       type Woman  is new Person(Female);

    end Persons2;

    package Persons3 is

       type Genders is (Male, Female, Unknown);

       type Person is private;
       type Man is private;
       type Woman is private;

    private

       generic
           The_Gender : Genders := Unknown;
       package Generic_Persons is
           type Person is record
               Age            : Integer := 0;
               Name           : String (1..256) := (others => Character'Val(0)); -- '
               Height, Weight : Float := 0.0;
               Gender         : Genders := The_Gender;
           end record;
       end Generic_Persons;

       package Person_Pkg is new Generic_Persons(Unknown);
       package Man_Pkg is new Generic_Persons(Male);
       package Woman_Pkg is new Generic_Persons(Female);

       type Person is new Person_Pkg.Person;
       type Man    is new Man_Pkg.Person;         
       type Woman  is new Woman_Pkg.Person;

    end Persons3;

begin
    null;
end jdoodle;

答案 1 :(得分:0)

Ada 2012解决方案:

type Person is tagged record
   -- ...
   Gender : Genders := Unknown;
end record with Type_Invariant => (Person.Gender = Unknown);

type Man is new Person with null record
  with Type_Invariant => (Man.Gender = Male);
type Woman is new Person with null record
  with Type_Invariant => (Woman.Gender = Female);

我不确定这是否适用于非标记类型。

答案 2 :(得分:0)

使用普通的Ada 95(为避免为软件包ManWoman提供主体而作弊):

private with Ada.Strings.Unbounded;

package Person is

   type Age_In_Years is range 0 .. 200;
   type Weight_In_kg is delta 0.1 range 0.0 .. 300.0;
   type Height_In_m  is delta 0.01 range 0.0 .. 3.0;
   type Genders      is (Male, Female);

   type Instance is abstract tagged private;
   subtype Class is Instance'Class; -- '

   function Age    (Self : in Instance) return Age_In_Years;
   function Name   (Self : in Instance) return String;
   function Weight (Self : in Instance) return Weight_In_kg;
   function Height (Self : in Instance) return Height_In_m;
   function Gender (Self : in Instance) return Genders is abstract;

private

   type Instance is abstract tagged
      record
         Age    : Age_In_Years;
         Name   : Ada.Strings.Unbounded.Unbounded_String;
         Weight : Weight_In_kg;
         Height : Height_In_m;
      end record;

end Person;
with Person;

package Man is

   subtype Parent is Person.Instance;
   type Instance is new Parent with null record;
   subtype Class is Instance'Class; -- '

   overriding
   function Gender (Self : in Instance) return Person.Genders is (Person.Male);

end Man;
with Person;

package Woman is

   subtype Parent is Person.Instance;
   type Instance is new Parent with null record;
   subtype Class is Instance'Class; -- '

   overriding
   function Gender (Self : in Instance) return Person.Genders is (Person.Female);

end Woman;