软件构造学习心得——第二部分ADT+OOP(4-8讲)(上)

软件构造学习心得——第二部分ADT+OOP(4-8讲)(上)

内容

基本数据类型、对象数据类型
静态类型检查、动态类型检查
Mutable/Immutable
值的改变、引用的改变
防御式拷贝
Snapshot diagram
Specification、前置/后置条件
行为等价性
规约的强度
ADT操作的四种类型
表示独立性
表示泄露
不变量、表示不变量RI
表示空间、抽象空间、AF
以注释的形式撰写AF、RI
接口、抽象类、具体类
继承、override
多态、overload
泛型
等价性equals()和==
equals()的自反、传递、对称
hashCode()
不可变对象的引用等价性、对象等价性
可变对象的观察等价性、行为等价性

基本数据类型、对象数据类型

基本数据类型:int、long、boolean、char、double(小写开头)
对象数据类型:String、BigInteger(大写开头)
在这里插入图片描述
对象数据类型有继承关系
在这里插入图片描述

静态类型检查、动态类型检查

前者在编译阶段进行类型检查,后者在运行阶段进行类型检查
必然的,静态类型检查 >>(好于) 动态 >>(好于) 无检查

静态类型检查:可在编译阶段发现错误,避免了将错误带入到运行阶段,可提高程序正确性/健壮性
静态:关于“类型”的检查,不考虑值
在这里插入图片描述
动态:关于“值”的检查
在这里插入图片描述
除0错误不是动态!

Mutable/Immutable&&值的改变、引用的改变&&防御式拷贝&&Snapshot diagram

赋值:数据改变/引用改变

尽量使用final变量(引用不变)作为方法的输入参数、作为局部变量
final类无法派生子类
final变量无法改变值/引用
final方法无法被子类重写

不变对象:一旦被创建,始终指向同一个值/引用
可变对象:拥有方法可以修改自己的值/引用

eg:
String 是immutable的
在这里插入图片描述
StringBuilder是mutable的
在这里插入图片描述
当只有一个引用指向该值,没有区别;有多个引用的时候,差异就出现了

可变的优势:
性能更好、共享

不可变优势:
更“安全”,在其他质量指标上表现更好

如何改进:
1.防御式拷贝(new…)
2.局部变量,不会涉及共享;只有一个引用
3.包装器
在这里插入图片描述
snapshot:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
eg:
在这里插入图片描述

Complex data types: Arrays and Collections(list、set、map)都是mutable的,迭代器也是mutable的

这里subjects是ArrayList
在这里插入图片描述
注意不能用subjects.remove

包装器:将mutable转为immutable
在这里插入图片描述

Specification、前置/后置条件、强度

规约:只讲“能做什么”,不讲“怎么实现”
提高代码效率、解耦
在这里插入图片描述

在这里插入图片描述
异常:前置条件不满足
前置条件不满足,则方法可做任何事情。
– “你违约在先,我自然不遵守承诺”

在这里插入图片描述
在这里插入图片描述

尽量避免使用mutable的对象作为参数,且尽量不改变输入参数

规约的强度:
spec变强:更放松的前置条件+更严格的后置条件
强的规约可以替代弱的规约!
可以比不出强弱!

图:
在这里插入图片描述
在这里插入图片描述

在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度;
不写Precondition,就要在代码内部check;若代价太大,在规约里加入precondition, 把责任交给client
惯用做法是:不限定太强的precondition,而是在postcondition中抛出异常:输入不合法

ADT操作的四种类型

可变类型的对象:提供了可改变其内部数据的值的操作
不变数据类型: 其操作不改变内部值,而是构造新的对象
四种类型:(考试时给一个方法问是什么类型)
在这里插入图片描述
构造器:可能实现为构造函数或静态函数(工厂方法)
变值器:通常返回void,如果返回值为void,则必然意味着它改变了对象的某些内部状态,当然也可以返回其他的,比如boolean,或者自己

immutable, has no mutators.
在这里插入图片描述

表示独立性&&表示泄露&&不变量、表示不变量RI&&表示空间、抽象空间、AF&&以注释的形式撰写AF、RI

表示独立性:client使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。
除非ADT的操作指明了具体的pre- 和post-condition,否则不能改变ADT的内部表示——spec规定了client和implementer之间的契约。

不变量:在任何时候总是true
eg:immutability就是一个典型的“不变量”

在这里插入图片描述
表示泄露:外部代码可以直接改变内部表示

除非迫不得已,否则不要把希望寄托于客户端上,ADT有责任保证自己的invariants,并避免“表示泄露”。最好的办法就是使用immutable的类型,彻底避免表示泄露

RI和AF:
在这里插入图片描述
AF : R → A,映射,抽象函数,必满射,未必单射
RI : R → boolean,表示空间值的合法性(要会写RI!)
表示不变性RI:某个具体的“表示”是否是“合法的”
也可将RI看作:所有表示值的一个子集,包含了所有合法的表示值
也可将RI看作:一个条件,描述了什么是“合法”的表示值

不同的内部表示,需要设计不同的AF和RI
选择某种特定的表示方式R,进而指定某个子集是“合法”的(RI),并为该子集中的每个值做出“解释”(AF)——即如何映射到抽象空间中的值。

即使是同样的R、同样的RI,也可能有不同的AF,即“解释不同”。

**checkRep()**在所有可能改变rep的方法内都要检查
Observer方法可以不用,但 建议也要检查,以防止你的“万一”

在这里插入图片描述
在这里插入图片描述
几种方式:
防御拷贝
包装器
返回immutable类

检查保持不变量的三种方式:
在这里插入图片描述

本博客完成于6/20,于7/3修改
下篇链接

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值