3-1 数据类型(data type)与类型检验(type checking)
怎样构建 “类”(属性+方法)
①什么是datatype
②两种设计类的⽅式 ( static&dynamic )
mutable可变 immutable不可变
③ Snapshot 图
④集合类 Complex datatype Arrays collections
⑤实⽤的 immutable类型
理论基础 - ADT
技术基础 - OOP
1.data type
1.基本数据类型 2.对象数据类型
2.对象类型形成层次结构
Object extends ,继承关系,实现(接口继承)
严格的语义限制
纠正:静态>动态
静态检查:关于“类型”的检查,不考虑值
动态检查:关于“值”的检查
3.可变性&不可变性
改变一个变量:将该变量指向另一个值的存储空间
改变一个变量的值:将该变量当前指向的值的存储空间中写入一个新的值
①final
- final类⽆法派⽣⼦类
- final变量⽆法改变值/引⽤
- final⽅法⽆法被⼦类重写
②
不变对象:一旦被创建,始终指向同一个值/引用
可变对象:拥有方法可以修改自己的值/引用
也就是说,当tb加上“c”时,对应的sb值也会被修改。
但使用不可变类型,对其频繁修改会产生大量的临时拷贝(需要垃圾回收)
使用可变数据类型,可获得更好的性能,也适合于在多个模块之间共享数据
mutable可变数据类型
① 可获得更好的性能
(改变时不⽤保存多个副本,减少java垃圾回收的时间 )
② 适合于在多个模块之间共享数据
ps:
- 注意全局变量的使⽤
- 判断内容有⽤⽆⽤,是否有变量/引⽤指向它
- ⼀般创建对象都是不可变类型
例1
没有额外声明不能改变输入变量的值
错误难于跟踪和发现,且对于程序员说也难以理解
例2
不能⽤immutable时对mutable进⾏改造 :
防御式拷⻉(defensive copying):不直接返回引⽤,返回⼀个新的对象
return new Date(groundhogAnswer.getTime());
通过防御式拷贝,给客户端返回一个全新的Date对象
缺点:大部分时候拷贝不会被修改,可能造成大量内存浪费
如果使用不可变类型, 则节省了频繁复制的代价
①没有改变属性值的⽅法
②private
③不能暴露属性的引用
安全的使用可变类型:局部变量,不会涉及共享;只有一个引用
如果有多个引用(别名),使用可变类型就非常不安全
4 Snapshot diagram
描述运⾏时对象在内存中的分布情况
Code->moment->Run time
- 不可变对象:用双线椭圆
- 不可变的引用:用双线箭头
引用是不可变的,但指向的值却可以是可变的
可变的引用,也可指向不可变的值
5 迭代器
mutable类型
6 基本immutable类型
基本类型及其封装对象类型都是不可变的
- 对象的属性和对象⼀起放在堆中 (属性可以是基本data type)
- 对对象的引用存在栈中
int a = 3 基本数据类型无id,a这个名字不会存入栈中,直接被替换成3
3-2 设计规约(designing specification)
1.基本内容
① 函数 ,⽅法 FunctionMethod
② 规约:定义和描述,注意事项
③ 如何设计规约
2.API documentation
代码中变量的数据类型定义:final
(1)输入/出的数据类型
(2)功能,正确性
(3)性能
只讲能做什么,不讲如何实现
3.Behavioral equivalence⾏为等价性
是否可相互替换
①站在客户部视⻆看⾏为等价性
②根据规约判断⾏为是否等价
单纯的看实现代码,并不足以判定不同的 implmentation是否是 “行为等价的”
需要根据代码的spec (开发者与client之间形成的contract)判定行为等价性
4.规格结构
requires 前置条件:对客户之间的约束,使⽤⽅法时必该满⾜的条件
effects 后置条件:对开发者的的约束,⽅法结束时必须满⾜的条件
契约:前置条件满⾜了,后置条件必须满足;前者违法后者怎么样都⾏
(最好抛出异常 避免浪费时间)
5.静态类型声明
静态类型声明是一种规约,可据此进行静态类型检查static checking
⽅法前的注释也是一种规约,但需人工判定
规约中包含什么内容:
ps:
- 除⾮在后置条件⾥声明过,否则⽅法内部不应改变输入参数
- 尽量不⽤mutating
- 程序中可能有很多变量指向同一个可变对象(别名),⽆法强迫类的实现体和客户端不保存可变变量的“别名”(contracts can’t be enforced in just one place anymore)
6.测试
依据规的设计测试⽤例
不考虑实现,同其他client⼀样
7.设计规约
确定的规约:给定一个满⾜先决条件的输入,其输出是唯一的,明确的
欠定的规约:同⼀个输入可以有多个输出情况( 通常有确定的情况)
⾮确定的规约:同⼀个揄多次执⾏的得到的揄出可能不同
3-3 抽象数据类型(ADT)
1.在类的实现上做约束:不能用属性,只能用其提供的方法
①提供足够方法操纵属性
②public的属性设计不好
③private:表示独立性,不用管属性的类型
2.如何设计类的属性:
抽象函数AF和表示不变量RI(给程序员看的)
用户自定义的类型
数据抽象:强调“作用于数据上的操作”
对于设计类:immutable和mutable的差别在于实现.java无法识别
3.
4.如何设计一个ADT
①简单
②足以支持所有操作需要
③表示独立性(representation independence)
客户使用ADT时无需考虑其内部如何实现
ADT内部表示的变化不应影响外部spec和客户端
5.如何测试一个ADT
RI(表示不变性)(某个具体的“表示”是否合法 ):
看作⼀个条件⼀ 描述了什么是“合法”的表示值
看作所有表示值的⼀个⼦集 ⼀包含了所有合法的表示值
1.不同RI限制不同集合
2.同RI不同AF->解释不同
3.RI由谁去做 ?
检测难度不⼤时,都可
检测难度大时,例:数组是否已排序的检测,只能靠clint
3-4 面向对象编程(OOP)
OOP:object Oriented Programming
interface:只有操作,没有具体属性和实现,纯抽象类,不可实例化
接口:确定ADT规约
类:实现ADT
①接口中无structor
② 抽象类返回值应该也为抽象的
③类可以包含接⼝中没有的⽅法,但接⼝中的所有⽅法必须出现在类中
如何创建 ⼀个新的对象?静态方法:返回⼀个具体对象 static
(二)继承和重写 Inheritance&Overriding
①严格继承:⼦类不能添加新⽅法,⽆法重写超类中的⽅法
②super()
③重写时不要改变原⽅法的本意
(三)多态 ⼦类型 重载 polymorphism&subtyping&overloading
重载:多个方法共用一个方法名,参数列表不同
方便client调用:可⽤不同的参数列表词⽤同样的函数
② 根据变量类型决定调⽤⽅法
如果Animal是interface 那么第⼀个会报编译错误
③ Overriding & Overloading
④参数型多态 ⼀ 泛型
-
可定以多个泛型 Map<E,F,>
-
通配符
-
运行时的泛型擦除 getClass()=list 不能⽤instanceof ()来确认其类型
-
不能定义泛型数组