软件构造学习笔记【三】(第4、5章)


从本篇起,我会较简洁的提炼重点知识点内容而非泛泛地了解知识点。这次笔记我们主要学习第三部分。

一、数据类型与类型检验

1.1 数据类型

数据类型的概念如下:
数据类型:一组值以及可以对其执行的操作。
变量:用特定数据类型定义,可存储满足类型约束的值。

1.1.1 基本数据类型

基本数据类型内容如下:

– int (for integers like 5 and -200, but limited to the range ± 2^31, or roughly ± 2 billion)
– long (for larger integers up to ± 2^63)
– boolean (for true or false)
– double (for floating-point numbers, which represent a subset of the real numbers)
– char (for single characters like ‘A’ and ‘$’ )

1.1.2 对象数据类型

对象数据类型内容如下:

– String represents a sequence of characters.
– BigInteger represents an integer of arbitrary size.

不属于基本数据类型的所有类型都是对象数据类型。
可以看出,对象数据类型首字母大写,而基本数据类型首字母是小写。
在这里插入图片描述

图1.1 两种数据类型的特点

Object类型是所有对象类型的父类,所有类若没有继承默认以Object为父类

1.2 类型检查

首先我们要了解类型转换,相关内容与在计算机系统学习的内容相同,分为显示类型转化和显示类型转化等,因此需要对这些进行检查。
静态类型语言:在编译阶段进行类型检查,所有变量的类型在编译期就已经确定。
动态类型语言:在运行阶段进行类型检查,变量的类型在运行期才能确定。
java属于静态类型语言,同时具有静态检查和动态检查。
静态检查

  1. 检查是否有语法错误。
  2. 名称错误。
  3. 参数个数错误。
  4. 参数类型错误。
  5. 返回值类型错误。

动态检查

  1. 非法参数:比如x/y中y为0就是不合法。
  2. 不可描述的返回值:即该返回值不能作为代表出现在该类型中。
  3. 超出范围的索引值:如数组越界等。
  4. 调用空对象的方法。

静态检查针对类型与特定值无关的错误,动态检查针对由特定值引起的错误。

1.2.1可变性和不可变性

1.2.1.1 变与不变

改变可以分成两种:
改变一个变量:将该变量指向另一个值的存储空间。
改变一个变量的值:将该变量当前指向的值的存储空间中写入一个新的值。

同时,不变性还可分成以下两种:
不变数据类型(immutable type):一旦被创建,其值不能改变
引用不变(immutable references):一旦确定其指向的对象,不能再被改变(但其值是可能变化的)

1.2.1.2 final

引用不变性可以利用final关键字产生。
一个,无论它是可变的或是不变的,都可加上final关键字,使其具有如下特质:
final 类无法派生子类
方法变量也可以加final:
final 方法无法被子类重写
final 变量无法改变其引用(而非值)

1.2.2可变类型(mutable)和不可变类型(immutable)

不可变类型
一旦被创建,就始终代表(对外表现出)同样的值。
在这里插入图片描述

图1.2 不可变类型

可变类型
拥有方法可以修改自己的值。
在这里插入图片描述

图1.3 可变类型

不可变类型安全,而可变类型比较方便。

1.2.3 程序快照图

属于程序的运行时视图、代码级视图、瞬间视图。
基本类型
在箭头末端填写值。
在这里插入图片描述

图1.4 基本类型

对象类型
在箭头末端画一个椭圆,在其中写上对象的类名,更详细的话再包含内部属性。
可变类型对象的椭圆使用单线,而不可变类型的椭圆使用双线。
在这里插入图片描述

图1.5 对象类型

引用
可变引用使用单线,不可变引用使用双线。
在这里插入图片描述

图1.5 可变和不可变引用

这里需要注意,即使是immutable的数据也可变引用,而mutable的数据上了final就是不可变引用的。这两点需要分开看待。

1.2.4 容器

经典的容器包括数组、map、set、list等。数组长度确定,而其他长度可变。典型的程序快照如下:
在这里插入图片描述

图1.6 典型的快照

迭代器:可变数据类型,有方法next返回下一个类型,hasnext返回是否有下一个类型。
在这里插入图片描述

图1.6 迭代器

1.3 总结

基本数据类型不可变,包括大数类型BigInteger等;
一般容器都可变。如果希望容器不可变,可使用包装器 Collections.unmodifiableList 等获取一个不可变的包装对象;
程序快照图非常重要。画法如下:

可变不可变
基本类型箭头末端
对象类型单椭圆双椭圆
引用(final)单箭头双箭头
表1 程序快照图画法

此外,变量名也要画出,但不用画圆圈。

二、设计规约(spec)

类中包含方法,参数,返回值等,方法中的主函数可以作为客户端;对于非参数和返回值的类型检测在在静态类型检查阶段完成。针对这些内容我们需要设计规约。

2.1 规约

规约是客户端与实现者之间签订的“契约”,客户端的输入应当满足前置条件,实现者编写的程序应当给出满足后置条件的结果。
规约描述了方法的功能以及接口(“能做什么”),不需要依赖(也不应该透露)方法的具体实现。
Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守。同时spec不能涉及内部变量私有域。

2.2 行为等价性

去判断行为等价性,问题的关键就在于两种实现方法能否相互替代。
两种行为等价的方法可以相互替代,主要看用户需求。

2.3规约内容

前置条件(Precondition):
规约的前置条件是对客户端的约束,即客户端在使用这个方法的时候必须要满足的要求。
后置条件(Postcondition):
规约的后置条件是对开发者的约束,即开发人员在完成方法后需要满足的条件。
异常行为(Exceptional behavior):
规约中做的规定,如果违反前置条件那么方法会怎么做,返回什么值。
同时,如果客户端没有满足前置条件,那么方法可以做任意事情。

2.4 java中的规约

java中的规约包括注释、@param、@return、@throws。其中@param属于前置条件,@return、@throws属于后置条件。

2.5 规约的强弱

java中的规约是分强弱的,较强的规约有以下的特征:
前置条件较弱,后置条件较强
也就是给用户的自由度更大了,因此用户会比较需要强的规约,同时会使得方法更难实现。
注意,抛出的异常更少和返回的内容更详细时会加强后置条件。

2.5.1 规约图

规约图是规约强弱的表示,越小的圈代表了越强的规约(能让它实现的函数越少)。强规约的函数无法用弱规约的函数替代。
在这里插入图片描述

图2.1 归约图

2.6 其他的分类方法

按照确定性分类
确定性规约(Deterministic):给定前置条件,其输出是唯一的、明确的。
欠定的规约(Underdetermined):同一个输入可以有多个输出,但是一旦使用具体的方法实现了这个规约,那么这个返回值也将会被确定。
非确定的规约(Not deterministic):同一个输入,多次执行可能得到多个结果,比如涉及到随机数的方法。
按照陈述性分类
操作式规约:有具体的实现细节,如伪代码
声明式规约:没有内部实现的描述,只有对输入输出的规定
声明式规约更有价值,更能应对变化。但是操作式规约能够方便开发。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值