软件构造(4)

OOP

1.    Interface
接口

接口的成员变量默认用final关键字修饰,故必须有初值,可用public,default修饰,可用static修饰。

接口的方法只能被public、default、abstract、static、strictfp(严格浮点运算)修饰。

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

1.    Inheritance、override 继承和重写

Strict
inheritance 严格继承:子类只能添加新方法,无法重写超类(父类)中的方法(final限制)。

考虑final修饰类、方法、属性时的不同作用。

Override
方法:具有一致的signature,复用的基本机制。

父类型中的被重写函数体不为空:意 味着对其大多数子类型来说,该方法 是可以被直接复用的。

如果父类型中的某个函数实现体为空, 意味着其所有子类型都需要这个功能, 但各有差异,没有共性,在每个子类中 均需要重写。

、抽象类:只有定义没有实现,由关键字abstract定义,抽象类不能实例化(不能用new 生成对象),继承某个抽象类的子类在实例化时,所有父类中的 抽象方法必须已经实现

1.    Polymorphism
,subtyping
and overloading 多态,子类型化,重载

三种多态:

1.    Ad
hoc polymorphism (特殊多态)

用于function
overloading(功能重载),即重载

一个方法可以有多个同名的实现(方法重载)

2.    Parametric
polymorphism (参数化多态)

泛型

一个类型名字可以代表多个类型(泛型编程)

3.    Subtyping
(subtype polymorphism / inclusion
polymorphism )(子类型多态、包含多态)

一个变量名字可以代表多个类的实例(子类型)

1.       
Overloading 重载

1.       
重载条件:

1.       
方法名相同

2.       
参数列表不同,即参数类型、个数、类型顺序至少有一项不相同

3.       
返回值类型可以不同

4.       
方法的修饰符可以不同

5.       
可以抛出不同的异常

6.       
可以在类内重载,也可以在子类重载

2.       
重载是一种静态多态,静态类型检查

(static dispatch 静态分派)并在编译阶段决定具体执行哪个方法(即对方法的调用取决于编译时声明的引用的类型)

而重写(dynamic dispatch 动态分派)则进行动态类型检查,根据运行时堆中的实例类型选择方法。

重写时父类和子类中的方法具有相同的签名,签名不同时则为重载,子类重载了父类的 方法后,子类仍然继承了被重载的方法

2.       
Generic 泛型

使用泛型变量的三种形式:泛型 类、泛型接口和泛型方法

1.       
通配符

<?> :只有使用泛型的时候出现,不能在定义中出现。

2.

类型擦除:编译后、运行时类型擦除

List
-> List

注意可能引起重载编译错误。

运行时不能用 instanceof 检查泛型。

3.       
不能创建泛型数组

不能用在静态变量

不能创建对象(不能new)

3.       
Subtypes

超类的子类型,如:ArrayList和LinkedList是List的子类型。

子类型的规约不能弱化超类型的规约。

1.       
子类型多态:不同类型的对象可以统一处理而无需区分(不加区分地调用同样的方法等),从而隔离变化

2.       
LSP(Liskov Substitution Principle) 如果S是T的子类型,那么T的对象可以被S的对象替换。

3.       
Type casting 类型转换

避免向下类型转换。

4.       
Dispatch 分派

Static dispatch 静态分派

Dynamic dispatch 动态分派

将调用的名字与实际方法的名字联系起来(可能有多个)

决定具体执行哪一个操作

重载,在编译阶段即可确定执行哪个具体操作

重写,在运行时决定

Early/static binding

Lade/dynamic binding

绑定static、private、final方法时发生

重写父类子类的同样方法

1.    equals()

1.       
引用等价性

比较内存地址ID

用于比较基本数据类型

2.       
对象等价性
equals()

验证正确性:reflexive 自反性、symmetric 对称性、transitive 传递性、非空(a.equals(null) return false)

对基本数据类型,使用==判定相等

对对象类型,使用equals()

如果用==,是在判断两个对象身份 标识
ID是否相等(指向内存里的同一段空间)

hashCode()

等价的对象必须有相同的hashCode

Rule:重写equals时重写hashcode

1.

1.    Equality
of Mutable Types 可变对象的等价性

Observational
equality 观察等价性

Behavioral equality
行为等价性

在不改变状态的形况下,两个mutable看起来是否一致

调用对象的任何方法都展示出一致的结果

调用observer,producer,creator

调用任何方法,包括mutator

当前情况下,看起来(如成员变量)相同

经过改变后,依然相同(只是别名引用)

对不可变类型,观察等价性和行为等价性完全等价。

对可变类型,往往倾向于实现严格的观察等价性。(但有时观察等价性可能导致bug,甚至破坏RI)

对可变类型,应当实现行为等价性,即只有指向内从空间中同样的objects才相等(即equals比较引用,如==而hashcode把引用映射为一个值)。

所以对可变类型,无需重写equals和hashcode,直接继承object。(比较引用)

若一定要判断两个可变对象是否一致,最好定义一个新的方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值