- 封装(encapsulation)
所有信息都存贮在对象中
- 即其数据及行为都封装在对象中
影响对象的唯一方式是执行它所属的类的方法即执行作用于其上的操作
- 多态是指能够在不同上下文中对某一事物(变量、函数或对象)赋予不同含义或用法
- 属于某个类的对象称为该类的一个实例(instance)
- 对象数组的创建
- 数组的分配和创建
- 数组所包含对象的分配和创建
- 声明在栈内存中,new在堆内存中
- 元类
- 描述类的类 如果将类看作一个对象,该类必定是另一个特殊类的实例 这个特殊类我们称作元类
- 消息:对象间互相请求互相协作的途径
- 动态类型面向对象语言:一般在变量使用之前不需要声明变量类型,而变量的类型通常是由被赋的值的类型决定,类型的检查是在运行时做的
静态类型面向对象语言:类型的检查是在编译时做的,编程时需要明确声明变量类型
- 方法绑定:一个对象接到消息将消息名与要执行的代码进行绑定。
静态方法绑定:在编译时刻进行方法绑定
动态方法绑定:在运行时刻进行方法绑定
对比:动态绑定灵活性相对静态绑定来说要高,因为它在运行之前可以进行选择性的绑定。但动态绑定的执行效率要低些,实现起来更加复杂。
- 静态方法绑定和动态方法绑定优缺点
- 缺点:耦合性高;灵活性低
- 优点:执行速度快,效率高;编译时触发,可以提前知道程序错误
- 优点:灵活性高,运行时候才触发,可修改性强;耦合性低
- 缺点:执行速度和效率比静态方法绑定低;不可以提前预知错误,有编译器不可预见的错误而产生很多程序漏洞
静态方法绑定:
动态方法绑定:
- 替换原则
- 最小静态空间分配:只分配基类所需的存储空间。
- 最大静态空间分配:无论基类还是派生类,都分配可用于所有合法的数值的最大的存储空间。
- 动态内存分配:只分配用于保存一个指针所需的存储空间。在运行时通过堆来分配数值所需的存储空间,同时将指针设为相应的合适值。
用子类替换父类(任何父类出现的地方都能用子类来替代)
分配方案
考过简答题(三点+对三点的解释)
C++保证变量x只能调用定义于Window类中的方法,不能调用定义于TextWindow类中的方法。
定义并实现于Window类中的方法无法存取或修改定义于子类中的数据,因此不可能出现父类存取子类的情况。
C++规则: 对于指针(引用)变量:当消息调用可能被改写的成员函数时,选择哪个成员函数取决于接收器的动态数值。 对于其他变量:关于调用虚拟成员函数的绑定方式取决于静态类(变量声明时的类),而不取决于动态类(变量所包含的实际数值的类)。
分配变量值可能使用的最大存储空间。
堆栈中不保存对象值。
堆栈通过指针大小空间来保存标识变量,数据值保存在堆中。
指针变量都具有恒定不变的大小,变量赋值时,不会有任何问题。
Smalltalk、Java都采用该方法。
- 抽象类
在定义方法时可以只给出方法头,而不必给出方法体、即方法实现的细节,这样的方法被称为抽象方法。
特性:
抽象方法必须使用关键字abstract修饰(Java语言),包含抽象方法的类必须声明为抽象类。
抽象类不能被实例化。
接口
只包含静态最终变量和抽象方法,或者是只有抽象方法的时候,抽象类可以等同于一个接口,接口是特殊的抽象类
接口里的常量和方法的定义可以省略,因为所有定义在接口中的常量都默认为public、static和final;所有定义在接口中的方法默认为public和abstract
实现类可以实现多个接口。(多个接口间用”,”分隔)
接口不可以被实例化。
实现类必须实现接口的所有方法(抽象类除外)。
接口中的变量都是静态常量。
(JAVA语法规定,接口中的变量默认自动隐含是public static final)
Java接口中不能有方法体实现。
- 继承的形式
特化子类化(子类型化):子类是父类的一个实例,ppt里有详细定义
规范子类化:继承方法定义,实现各不相同
5种坏的(不提倡的)继承方式:
构造子类化:
泛化子类化
扩展子类化
限制子类化
变体子类化
结合子类化(C++支持多继承,java不支持多继承,通过接口实现)
- 编译器匹配步骤
第一步,找精确匹配(形参实参精确匹配的同一类型)找到,则执行,找不到转第二步。
第二步,找可行匹配(符合替换原则的匹配,即实参所属类是形参所属类的子类),没找到可行匹配,报错;只找到一个可行匹配,执行可行匹配对应的方法;如果有多于一个的可行匹配,转第三步。
第三步,多个可行匹配两两比较,如果一个方法的各个形参,或者:与另一个方法对应位置形参所属类相同,或者:形参所属类是另一个方法对应位置形参所属类的子类,该方法淘汰另一个方法。
最后,如果只剩一个幸存者,执行;如果多于一个幸存者,报错。
15. 组合、继承的优缺点
- 组合的优缺点:
- 缺点:容易产生过多的对象;为了可以组合多个对象,必须仔细对接口进行定义
- 优点:耦合性低,可修改性强;灵活性高;通过包含的对象去调用方法,封装性好
- 继承的优缺点:
- 优点:子类可以重写父类的方法来实现对父类的扩展;代码简洁
- 缺点:耦合性高,当父类代码改变时,继承的子类代码也需要改变;灵活性差;父类的细节对子类可见封装性差
- 应用场景:
如果语义满足“IS-A”且行为上满足LSP(里氏代换原则),则使用继承
如果语义上满足“HAS-A”,那么使用组合,或者按组合复用原则,优先考虑组合
- 多态的形式
- 重载(overloading):同一个类中,类型签名(参数类型、参数顺序和返回值类型)区分
- 改写(overriding):父类和子类中,相同类型签名
- 多态变量(polymmorphic variable)
Parent variable = new Child();
- 简单多态变量
- 接收器变量 多态变量最常用的场合是作为一个数值,用来表示正在执行的方法内部的接收器。
this
- 反多态(向下造型)
- 纯多态(多态方法)
向下造型是处理多态变量的过程,并且在某种意义上这个过程的取消操作就是替换。
- 泛型 Generic(考试不怎么考,但日常中编程中需要学会使用)
是指具有在多种数据类型上皆可操作的含意 。既编写的代码可以在不同的数据类型上重用。
- 代替与改进(重置/改写的方式)
- 代替(replacement):在程序执行时,实现代替的方法完全覆盖父类的方法。即,当操作子类实例时,父类的代码完全不会执行。
- 改进(refinement):实现改进的方法将继承自父类的方法的执行作为其行为的一部分。这样父类的行为得以保留且扩充。