我正在尝试在Ada中建模三个实体:Person
,Woman
和Man
。我希望Person
有一个字段Gender
,对于Unknown
,必须为Person
;对于Male
和{{1},必须是Man
} Female
。
我想将Woman
和Man
实现为Woman
字段分别为Person
和Gender
的{{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 }},而且我也不允许这样做。
可以做我想做的事吗?
答案 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(为避免为软件包Man
和Woman
提供主体而作弊):
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;