(1)万物皆对象 对象可以存储数据,也可以执行操作
(2)程序是对象的集合,它们通过发送消息来告知彼此所要做的
可以把消息想象为对某个对象的特定方法的调用
(3)每个对象都有自己的由其他对象所构成的存储
可以通过创建包含现有对象的包的方式来创建新类型的对象
(4)每个对象都拥有类型
每个对象都是某个类的一个实例
(5)某一类特定类型的所有对象都可以接收同样的消息
子类可以完全替代父类的所有功能
💡
Light lt = new Light();
lt.on();
面向对象要解决的是创建从问题空间到解空间的一对一的映射
接口确定了某一特定对象所能发出的请求
满足这些请求的代码和隐藏的数据构成了实现
调用方法 -> 向一个对象发送一个消息(产生请求)
向Light类的lt对象发送一个on()(打开)的请求
每个对象都提供服务
有助于提高对象的内聚性
程序开发按照角色分类类创建者和客户端程序员
**客户端程序员:**收集各种用来快速实现应用开发的类
**类创建者:**构建类,只向客户端程序员暴露必要的部分,而隐藏其他的部分
**访问控制:**客户端程序延不能访问类内的具体实现细节,接口对客户端程序员来说是一项服务
代码复用
组合:has-a的形式
聚合:动态发生的组合
继承: is-a的形式
类型等价性
2种方法使基类和导出类产生差异
- 直接在导出类中添加新的方法
- 覆盖,在导出类中重写基类中已有方法的新的实现
导出类对基类是完全替代,符合替代原则
在导出类中添加新的接口元素,扩展了接口,新的类型替代基类并不完美,称为is-like-a关系,新类型具有旧类型的接口
把导出类型当作基类型来看,使用泛化的方法,而不用关心导出类型具体特化的类型,就能够执行特化的不同代码段
前期绑定 编译器产生一个对具体函数名字的调用,运行时将这个调用解析到将要被执行代码的绝对地址
后期绑定 OOP中运行时才能确定被调用代码的地址
Java使用一小段特殊的代码来替代绝对地址调用,这段代码使用在对象中存储的信息来计算方法体的地址,这样,每个对象都可以有不同的行为表现
在 Java 中,动态绑定是默认行为,不需要添加关键字来实现多态
向上转型将导出类看作是其基类
void doSomething(Shape shape) {
shape.erase();
shape.draw();
}
Circle circle = new Circle();
doSomeThing(circle);
**单根继承,**所有的类继承自Object类
**容器,**创建一种对象类型,这种对象持有其他类型的对象的引用,用以解决不知道需要多少空间来存储对象的问题(不知道要创建多少对象)
不同的容器,有不同的操作(接口),有不同的效率
参数化类型-向下转型
可以存储Object类型的容器可以存储任意一种对象,但是这些对象都会被向上转型成Object类型,需要通过向下转型特化为原来的类型
参数化类型机制 一个编译器可以定制作用于特定类型上的类,如编译器可以定制只存取Shape类型的类,这种类型称为范型
ArrayList<Shape> shapes = new ArrayList<Shape>();
对象的创建和生命周期
销毁对象
C++在堆栈中或静态区域中创建对象,编写程序时确定对象生命周期
Java在堆中创建对象,直到运行时才动态创建对象,创建对象所用时间远大于在堆栈中创建对象
C++必须通过编程来确定何时销毁对象,可能造成内存泄漏
Java通过垃圾回收机制,自动释放对象
异常处理:错误处理
- 异常是一种对象,它从错误的地点被抛出,由相应的异常处理器捕获,在错误发生时执行另一条路径
- 异常不能被忽略,必须得到处理
并发编程
把问题切分成多个可独立运行的部分,从而在同一时刻处理多个任务
并发要处理共享资源的问题