3.4面向对象的编程
课程目标
用oop、接口、类实现ADT
上一节学习了ADT理论,本节学习ADT的具体实现技术:OOP
大纲
面向对象的标准
OOP的基本概念
OOP的不同特性:
3.封装与信息隐藏
继承与重写
多态、子类型、重载
静态与动态分派
Java中一些重要的对象方法
设计好的类
OOP的历史
总结
3.4.1面对对象的标准
【泛型】对于“随时准备更变”和“设计/重用”:应该可以使用任意类型的参数来编写类
【继承】:应该可以定义一个类继承自另一个类,以控制由此产生的潜在复杂性。
【多态】:在基于继承的类型系统的控制下,应该可以将实体(代表运行时对象的软件的名称)附加到各种可能类型的运行时对象上。
【动态分派/绑定】:在实体上调用一个特性应该总是触发与附加的运行时对象类型相对应的特性,这在调用的不同执行中不一定是相同的。
3.4.2OOP的基本概念
对象:
一个对象是一组状态和行为
状态:就是在这个对象中的数据
——在java中,它们就是对象中的fields(基础变量)
行为:就是这个对象包含支持的动作
——在java中,它们被称为方法
——方法又被称为函数
——调用一个方法=使用一个函数
类:
每一个对象都有一个类
——一个类哦都包含方法和变量(fields)
——方法和变量(fields)共同作为成员
类定义了类型和实现
——类型≈对象可以在哪被使用
——实现≈对象怎么具体操作
简单来说,类的方法是它的应用程序编程接口(API)
——定义了用户如何和实例进行交互操作
静态方法使用的时候不需要实例化再调用
3.4.3接口interface:
—interface和class:定义和实现ADT
—接口之间可以继承
—一个类可以实现多个接口
—一个接口又可以有多种实现
接口里面可以没有构造器、没有fields甚至没有实现
接口的实现
客户端使用接口
Java的接口和类
接口:确定ADT规约spec
类:实现ADT
– 打破了抽象边界,接口定义中没有包含constructor,也无法保证所有实现类 中都包含了同样名字的constructor。
– 故而,客户端需要知道该接口的某个具体实现类的名字
接口的好处
接口为客户指定契约,仅此而已。
抽象数据类型的多个不同表示可以共存于同一个程序中,作为实现接口的不同类。
为什么要进行多实现
不同的实现
不同的行为
性能和行为往往不相同
3.4.4封装和信息隐藏
接口的信息隐藏:
使用接口类型声明变量
客户端仅使用接口中定义的 方法
客户端代码无法直接访问属性
成员的可见性修饰符:
private – Accessible only from declaring class只能从声明类中访问
protected – Accessible from subclasses of declaring class (and within package) 可以从声明类的子类中访
问(以及在包中)
public – Accessible from anywhere从任何位置访问
3.4.5继承与重写
严格继承:子类只能添加新方法,无法重写超类中 的方法(通过final修饰)
(1)重写Override
重写 的函数:完全同样的signature
当子类包含一个覆盖超类方法的方法时,它也可以使用关键字super调用超类方法。
实际执行时调用哪个方法,运行时决定。
(2)抽象类(作为父类存)
3.4.6多态、子类型、重载
(1)三种多态性
Ad hoc polymorphism (特殊多态): function overloading (功能重载). 使用函数重载在许多语言中支持特设多态
Parametric polymorphism (参数化多态): 当编写代码时没有提及任何特定类型,因此可以透明地使用任何数量的新类型。 在面向对象的编程社区中,这通常被称为泛型或泛型编程。
Subtyping (子类型多态、包含多态): 当一个名称表示许多不同的类与一些常见的超类相关的实例
(2)特殊多态和重载
特殊多态用到重载:
(3)重载
重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型
价值:方便client调用,client可用不同的参数列表,调用同样的函数
重载是一种静态多态
根据参数列表进行 最佳匹配
静态类型检查
在编译阶段时决定要具体执行哪个方法 (static type checking)
重载规则:
必须含有不同的参数列表
可以相同/不同的返回值类型
可以相同/不同的public/private/protected
可以声明新的或更广泛的检查异常。
调用重载的方法:
(4)参数多态和泛型编程
当一个函数在一系列类型上统一工作时获得参数多态性; 这些类型通常具有一些共同的结构。
- 它能够以通用的方式定义函数和类型,以便它可以在运行时传递参数的基础上工作,即允许在没有完全指定类型的情况下进行静态类型检查。
- 这是Java中所谓的“泛型”。
类型变量是一个不合格的标识符。
- 它们由泛型类声明,泛型接口声明,泛型方法声明和泛型构造函数声明引入。
泛型类: 其定义中包含了类型变量- 这些类型的变量被称为类的类型参数。
- 它定义了一个或多个作为参数的类型变量。
- 泛型类声明定义了一组参数化类型,每个类型参数部分的每个可能的调用都有一个类型声明。
- 所有这些参数化类型在运行时共享相同的类。
泛型接口,非泛型的实现类
泛型接口,泛型 的实现类
(5)Subtyping (子类型多态、包含多态)
子类型的规约不能弱化超类型的规约。
子类型多态:不同类型的对象可以统一的处理而无需区分,从而隔离了“变化”
静态分派:编译阶段即可确定要执行哪个具体操作。
绑定:将调用的名字与实际的方法名字联系起来(可能很多个);分派:具 体执行哪个方法(early binding à static dispatch)
动态分派:编译阶段可能绑定到多态操作,运行阶段决定具体执行哪 个(override和overload均是如此);
推迟绑定:编译阶段不知道类型,一定是动态分派( override是推迟绑定,overload是early binding)