2020春季学期哈工大软件构造学习心得五

面向对象的编程

面向对象的标准

“准备更改”和“为重用而设计”的泛型(泛型):应该可以用表示任意类型的形式泛型参数编写类。
继承:应该可以将一个类定义为继承自另一个类,以控制由此产生的潜在复杂性。可能的是基于时间的各种类型的对象的继承(以时间为基础的对象类型)。
多态性:在基于继承的类型系统的控制下,应该能够将实体(软件文本中代表运行时对象的名称)附加到各种可能类型的运行时对象上。
动态调度/绑定:调用一个实体上的一个特性,应该总是触发与附加的运行时对象类型相对应的特性,在不同的调用执行过程中不一定是相同的。

OOP的基本概念

对象是状态和行为的集合体
State—对象中包含的数据。
—在Java中,这些是对象行为的字段
Behavior—对象支持的动作
—在Java中,这些被称为方法
—方法就是OO—代表函数
—调用方法=调用函数

OOP的独特特性

Interface和Class: 定义和实现ADT
接口之间可以继承与扩展
一个类可以实现多个接口(从而具备了多个接口中的方法)
一个接口可以有多种实现

接口:确定ADT规约;类:实现ADT
也可以不需要接口直接使用类作为ADT,既有ADT定义也有ADT实现
实际中更倾向于使用接口来定义变量
如:Set senate = new HashSet<>;而不用
HashSet senate = new HashSet<>;

java8的接口可以包含静态方法
当客户端使用接口类型时,静态检查确保它们只使用接口定义的方法。

封装和信息隐藏

利用接口隐藏信息:
使用接口类型声明变量
客户端仅使用接口中定义的方法
客户端代码无法直接访问属性

Overriding (覆盖/重写)

严格继承:子类只能添加新方法,无法重写超类中的方法
如果一个方法不能在Java程序中重写,那么它必须以关键字final作为前缀。

对于implement实现,抽象类实现某个接口,可以不实现所有接口的方法,可以由它的子类实现。而普通类即非抽象类则必须实现接口里的全部方法。
对于extend继承,则是否重写取决于自己的需求。

重写的函数:完全同样的signature,实际执行时调用哪个方法,运行时决定
父类型中的被重写函数体不为空:意味着对其大多数子类型来说,该方法是可以被直接复用的
对某些子类型来说,有特殊性,故重写父类型中的函数,实现自己的特殊要求
如果父类型中的某个函数实现体为空,意味着其所有子类型都需要这个功能,但各有差异,没有共性,在每个子类中均需要重写
重写之后,可利用super()复用了父类型中函数的功能,并对其进行了扩展

抽象类

至少包含一个抽象方法的类称为抽象类
接口:只有抽象方法的抽象类
Concrete class → \rightarrow Abstract Class → \rightarrow Interface

如果某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写
所有子类型完全相同的操作,放在父类型中实现,子类型中无需重写。
有些子类型有而其他子类型无的操作,不要在父类型中定义和实现,而应在特定子类型中实现

Overloading

重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型
好处是方便client调用,client可用不同的参数列表,调用同样的函数
重载是静态多态,静态类型检查
在编译阶段时决定要具体执行哪个方法 (static type checking)
与之相反,overridden methods则是在run-time进行dynamic checking

在这里插入图片描述
Set是一些其他类型E元素的有限集合的ADT
Set是泛型类型的一个示例:它的规范是根据稍后要填充的占位符类型
我们没有为Set string 和Set Integer 等编写单独的规范和实现,而是设计并实现了一个Set E 。

上界类型通配符:add方法受限
下界类型通配符:get方法受限
如果你想从一个数据类型里获取数据,使用 ? extends 通配符
如果你想把对象写入一个数据结构里,使用 ? super 通配符
如果你既想存,又想取,那就别用通配符
不能同时声明泛型通配符上界和下界

子类型的规约不能弱化超类型的规约
子类型多态:不同类型的对象可以统一的处理而无需区分

ADT和OOP中的“等价性”

等价关系
等价关系:自反、对称、传递

ADT是对数据的抽象, 体现为一组对数据的操作
抽象函数AF:内部表示 → \rightarrow 抽象表示
基于抽象函数AF定义ADT的等价操作

AF映射到同样的结果,则等价
站在外部观察者角度:对两个对象调用任何相同的操作,都会得到相同的结果,则认为这两个对象是等价的。 反之亦然!

==引用等价性(对基本数据类型,使用 = = 判断相等,是否指向内存里的同一段空间);equals() 对象等价性
在自定义ADT时,需要重写Object的equals()
Java编译器使用参数的编译时类型在重载操作之间进行选择。(静态类型检查)

当重写(override)equals()方法,除非对象被修改了,否则调用多次equals应同样的结果 ,“相等”的对象,其hashCode()的结果必须 一致,不相等的对象,也可以映射为同样的hashCode,但性能会变差
可用“是否为等价关系”检验你的equals()是否正确

Always override hashCode() when you override equals()
除非你能保证你的ADT不会被放入到Hash类型的集合类中

Overload vs. Override

可以使用强制类型转换

instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,
boolean result = obj instanceof Class
其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。

注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。instanceof不是使用静态类型检查的

Java中可变类型的等价性

观察等价性:在不改变状态的情况下,两个mutable对象是否看起来一致
行为等价性:调用对象的任何方法都展示出一致的结果
对可变类型来说,往往倾向于实现严格的观察等价性

如果某个mutable的对象包含在Set集合类中,当其发生改变后,集合类的行为不确定

对可变类型,实现行为等价性即可。也就是说,只有指向同样内存空间的objects,才是相等的。 所以对可变类型来说,无需重写这两个函数,直接继承Object的两个方法即可。 如果一定要判断两个可变对象看起来是否一致,最好定义一个新的方法。

所以不可变类型必须同时重写equals()和hashCode()
所以可变类型根本不应该重写equals()和hashCode()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值