在Java或C#中,您通常会有最终或只读的类成员 - 它们被设置一次然后再也不会被触及。它们可以为类的不同实例保存不同的值。
是……
你几乎已经有了一般的解决方案(对于不能成为判别式的情况)。该类型是私人有限的。软件包的客户端只能通过pkg提供的操作对其进行修改。只要操作不修改相关字段,就可以得到你想要的东西(除非我误解了,问题是如何防止自己修改pkg体中的字段)。
不,不是。
如果您的组件是离散类型或访问类型,则可以使其成为判别式,从而使其成为不可变的。
with Ada.Integer_Text_IO; procedure Immutable_Components is type Instance (Immutable : Positive) is null record; A : Instance := (Immutable => 1); begin Ada.Integer_Text_IO.Put (A.Immutable); -- A.Immutable := 2; -- assignment to discriminant not allowed: end Immutable_Components;
在回答这个问题之前,区分Ada和Java / C#的对象建模可能会有所帮助。在Java中,一切都是对象,因此所有常量都必须如此 final - 在Ada中,事物有点不同,Ada的对象系统(Ada用语中的“标记类型”)建立在两个项目上:记录和类型派生。这意味着,在教授OOP时,我们可以逐渐引入第一类型推导(例如 Type Degree is new Integer; ),然后记录(即封装) private -types(即信息隐藏),最后将所有内容与标记类型统一起来......所有这些我都认为你是认识到的。
final
Type Degree is new Integer;
private
在阿达,一个 constant 就是这样:一些可以读取但通常不会被写入的对象。 (例如内存映射的IO会让事情变得有趣。)所以我们可以说:
constant
Package Ex1 is Type Stub1 is private; -- Some type, with almost nothing public. C1 : Constant Stub1; -- A constant of that type. Private Type Stub1 is tagged record Data_1 : Integer; Data_2 : Float; end; -- And now we can tell the compiler what C1 _is_. C1: Constant Stub1 := (Data_1 => 3, Data_2 => 1.2); End Ex1;
这就是我们如何为标记类型创建常量,同时保持其实现细节隐藏;尽管如此,诚然,我们可以揭露一切,并摆脱整个 private 部分。
现在我们得到一个有趣的记录[和标记类型]称为判别式的特征 - 它们有点像常量,有点像其他语言中的泛型类型。使用判别式,我们可以根据消息长度制作一个大小不同的消息类型:
Package Ex2 is Type Message(Length : Natural) is private; -- A message. Function Create( Text : String ) return Message; Private Type Message(Length : Natural) is record Data : String(1..Length) := (Others => ' '); -- Defaults to space-filled string. end; Function Create( Text : String ) return Message is ( Data => Text, Length => Text'Length ); End Ex2;
现在,在这种情况下,当你做一个像 X : Message := Create("Steve"); 变量的类型[在这个例子中,不受约束,在这种情况下变得受约束 Message(5) (因为“史蒂夫”是5个字符)因此尝试使用不同大小的消息字符串重新分配是行不通的。 (所以,虽然你不能说 X:= Create("Why") 您 能够 说 X:= Create("Hello") 因为判别[ Length 这里是5.) - 因此,在某种情况下,判别式可以像常数字段一样起作用。
X : Message := Create("Steve");
Message(5)
X:= Create("Why")
X:= Create("Hello")
Length
该 limited 关键字意味着该类型没有赋值[但确实有初始化],所以你 可以 使整个类型表现为常量;这与单个组件不同 constant 但是,肯定不像它们之间的区别那样微妙 T 和 T'Class ( T'Class 是类型 T 以及由此衍生的所有类型 T 是 只要 那种类型。)
limited
T
T'Class