如何确定不变量是什么?
很简单,当设计一个新类时,我如何找出不变量应该是什么?不变量的定义是什么?我听说它与有效性有关,但这仍然含糊不清。是什么使给定实例有效或无效是有争议的。
我应该跟着我的“直觉”感觉走吗?是否有指导方针来找出不变量是什么?
Quite simply, when designing a new class, how do I figure out what the invariant should be? What defines the invariant? I've heard that it's tied into validity, but that's still ambiguous. What makes a given instance valid or invalid is debatable.
Should I just go with my "gut" feeling? Are there guidelines for figuring out what the invariant is?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不变式始终可以表示为谓词,参数是类的部分或全部状态变量(字段)。一类可以有多个不变量。例如,假设您有一个包含
initialBalance
、listOfTransactions
、currentBalance
的Account
类。此外,我们将交易保存在排序(按日期)列表中。对于此类,至少应维护两个不变量:1)initialBalance + sum(交易金额)= currentBalance
2) 对于 listOfTransactions 中的每个元素,位置
i
处的交易的timestamp
应始终小于位置处的交易的timestamp
j
如果i
j。
不变量取决于类正在做什么以及类的实现方式。
比方说,我们可以再添加一个状态变量:
closeDate
,并且会出现另一个不变量:在 closeDate 之后,任何交易都不能有日期。或者,如果列表不是按日期排序,而是按交易金额排序,则 invatians 会发生变化。
另一个例子:
假设您有一个 mutable
Ellipse
类,它定义了两个字段:r1
和r2
,其中包含的设置器>r1
和r2
。此类没有任何不变式,因为 r1 和 r2 的任何值都可以表示明确定义的椭圆。现在,假设您创建了新的
Circle
类来扩展可变的Ellipse
。圆只有一个半径,加上不变量为 (r1==r2)。为了保持不变性,你必须禁止有人设置 r1 或 r2,这样 r1!=r2 就会发生。另一方面,如果
Ellipse
和Circle
是不可变,则您不必关心对象生命周期中的不变量,因为仅在施工期间检查状况。通过前面的例子,我想解释一下
1) 不变量的建立和维护方式很大程度上取决于类之间关系的设计选择。
2)班级正在做什么
3)类是如何实现的。
不可变类在维护其不变性方面往往不太复杂,因为它们是在构造时建立的,并且永远不会改变。 (不变性还有许多其他好处 - 不在答案的范围内)
Invariant can be always represented as predicate with arguments being some or all state variables (fields) of the class. One class can have more then one invariant. For example, suppose you have an
Account
class that hasinitialBalance
,listOfTransactions
,currentBalance
. Also, we keep the transactions in a sorted (by date) list . for This class there are at least two invariants that should be maintained:1) initialBalance + sum(transaction amounts) = currentBalance
2) for every element in the listOfTransactions, the
timestamp
of the transactions at positioni
should be always less then thetimestamp
of the transaction at positionj
ifi < j
.Invariants depend on what the
class
is doing and also how the class is implemented.Let say, we can add one more state variable:
closedDate
, and one more invariant will appear: no transaction can have date after the closeDate.Or if the list is not sorted by date, but by transaction amount, then the invatians would change.
Another example:
Let's suppose that you have mutable
Ellipse
class defined with two fields,r1
andr2
which has setters forr1
andr2
. This class doesn't have any invariant, as any values for r1 and r2 can represent well defined ellipse.Now let's suppose that you create new
Circle
class that extends the mutableEllipse
. The circle has only one radius add the invariant would be (r1==r2). In order to maintain the invariant, you have to disallow somebody setting r1 or r2, such that r1!=r2 happens.On the other hand if the
Ellipse
andCircle
are immutable you don't have to care for the invariants during the life of the objects, as the condition would be checked only during construction.With the previous examples, i wanted to explain that
1) the way the invariants are established and maintained depends very much on the choice of design of the relations between the classes.
2) What the class is doing
3) How the class is implemented.
Immutable classes tend to be less complex to maintain their invariant, as they are established at construction, and never change. (Immutability has many other benefits too - not in scope of the answer)