Java之AF、RI

表示不变量和抽象函数

几个概念

表示域(space of representation values)里面包含的是值具体的实现实体。

抽象域里面包含的则是类型设计时支持使用的值。这些值是由表示域“抽象/想象”出来的,也是使用者关注的。

每一个抽象值都是由表示值映射而来:我们之前说过实现抽象类型的意义在于支持对于抽象值的操作,即我们需要能够创建和管理所有的抽象值,因此它们也必须是可表示的。

一些抽象值是被多个表示值映射而来的:这是因为表示方法并不是固定的,我们可以灵活的表示一个抽象值。

不是所有的表示值都能映射到抽象域中:在上面这个例子中,“abbc”就没有被映射。因为我们已经确定了表示值的字符串中不能含有重复的字符——这样我们的 remove 方法就能在遇到第一个对应字符的时候停止,因为我们知道没有重复的字符。

总之,一个ADT的实现不仅是选择表示域(规格说明)和抽象域(具体实现),同时也要决定哪一些表示值是合法的(表示不变量),合法表示会被怎么解释/映射(抽象函数)。

检查表示不变量

表示不变量不仅是一个简洁的数学概念,你还可以通过断言检查它的不变属性来动态捕捉bug。

这里举出一种检查的方法:

// Check that the rep invariant is true
// *** Warning: this does nothing unless you turn on assertion checking
// by passing -enableassertions to Java
private void checkRep() {
    assert denominator > 0;
    assert gcd(Math.abs(numerator), denominator) == 1;
}

应该在每一个创建或者改变表示数据的操作后调用 checkRep() 检查不变量,换句话说,就是在使用创建者、生产者以及改造者之后。

AF, RI以及表示暴露安全性的注解

应该在抽象类型(私有的)表示声明后写上对于抽象函数和表示不变量的注解,这是一个好的实践要求。

当在描述抽象函数和表示不变量的时候,注意要清晰明确:

对于RI(表示不变量),仅仅宽泛的说什么区域是合法的并不够,你还应该说明是什么使得它合法/不合法。

对于AF(抽象函数)来说,仅仅宽泛的说抽象域表示了什么并不够。抽象函数的作用是规定合法的表示值会如何被解释到抽象域。作为一个函数,我们应该清晰的知道从一个输入到一个输入是怎么对应的。

将表示暴露的安全性注释出来,这种注释应该说明表示的每一部分,它们为什么不会发生表示暴露,特别是处理的表示的参数输入和返回部分(这也是表示暴露发生的位置)。

下面是一个Tweet类的例子,它将表示不变量和抽象函数以及表示暴露的安全性注释了出来:

// Immutable type representing a tweet.
public class Tweet {

    private final String author;
    private final String text;
    private final Date timestamp;

    // Rep invariant:
    //   author is a Twitter username (a nonempty string of letters, digits, underscores)
    //   text.length <= 140
    // Abstraction function:
    //   AF(author, text, timestamp) = a tweet posted by author, with content text, 
    //                                 at time timestamp 
    // Safety from rep exposure:
    //   All fields are private;
    //   author and text are Strings, so are guaranteed immutable;
    //   timestamp is a mutable Date, so Tweet() constructor and getTimestamp() 
    //        make defensive copies to avoid sharing the rep's Date object with clients.

    // Operations (specs and method bodies omitted to save space)
    public Tweet(String author, String text, Date timestamp) { ... }
    public String getAuthor() { ... }
    public String getText() { ... }
    public Date getTimestamp() { ... }
}

可以看到,对于不可变类型的表示,表示暴露的安全性说明会简单很多。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值