一、什么是对象及面向对象
什么是对象?
● 哲学概念,对象(客体,Object)指可感知或可想像到的任何事物,既包括客观存在并可观察到的事物(如树木、房屋,抽象的如物价、事件),也包括想像的事物。
● 对象(object),是面向对象(Object Oriented) 中的术语,既表示客观世界问题空间中的某个具体的事物,又表示软件系统解空间中的基本元素。
● 在软件系统中,对象具有唯一的标识符,对象包括属性(Properties)和方法(Methods),属性就是需要记忆的信息,方法就是对象能够提供的服务。在面向对象(Object Oriented) 的软件中,对象(Object)是某一个类(Class)的实例(Instance)。
面向对象的方法学
包括:关联与聚合、封装、信息隐藏、消息传递、动态连接、实例化、泛化与多态。
面向对象与基于对象
● 面向对象,可以允许用户使用以上全部的原则。
● 基于对象,允许用户使用一些封装好的对象,调用对象的方法,设置对象的属性。但是他们无法让用户派生新对象类型。用户只能使用现有对象的方法和属性。(JavaScript,OCL)
二、封装与信息隐藏
封装
封装是指将对象的全部属性和全部的操作结合在一起,形成不可分割的独立单位,即对象。
1.使对象能够集中而完整地描述并对应一个具体事物。
2.体现了事物的独立性
3.减少内部修改对外部影响
4.编程麻烦\执行效率的损失
信息隐藏
信息隐藏是指对象与外界的交互中,尽可能地隐藏对象的内部细节,仅保留优先的对外接口与外部进行联系,而具体的实现细节对外是不可见的。
信息隐藏既可以隐藏属性,也可以隐藏操作。
一个对象信息隐藏的内容可随与之交互的对象的不同而改变。
公开静态的、不变的服务,而把动态的、易变的服务隐藏起来。
封装和信息隐藏是两个接近但有一定的区别的概念,不同的书和专家上有不同的看法。在实际的开发工作中很少有人区分。
如果区分一下的话,封装侧重于对数据,即将数据封装在对象内部,不允许其他对象访问。
信息隐藏侧重于对操作,有两个含义:一是对外提供操作的接口,对于操作是如何实现的,被隐藏了外界是看不到的。第二个含义就是可见性,一个对象的所有操作的接口并不是对任何其他对象都是可见的,而是上下文有关的,由该对象与其他对象的关系所决定。如果是针对以上的前提的话,该问题就很清楚了,“避免数据和函数的过度耦合”正是封装的原则,因为没有对象之前,程序的数据和函数之间并有约束,任何函数都可以访问任何数据,耦合性很大,对象的产生建立了约束规则,使得某些数据只能被某些函数所访问,也就是降低了整体数据耦合性。
“将编程错误限制在对象内部”实际是信息隐藏原则的目的,因为程序的行为行为逻辑体现在各个函数里,对象只向外提供接口,所以即使是有运行错误的话,与外界的行为关系不大,只需要检查对象内部的代码即可。
三、实例化
实例化
可以以类为模版产生属于该类的对象,这种根据类的产生对象的过程称为实例化。
实例化的意义
● 符合自然的思维方式
● 使得并发处理成为可能
四、消息传递
消息传递
● 只能通过向对方发送消息的发誓传递信息,这就是消息传递机制。
● 对象只能借助消息传递机制才能同其他对象通信。
● 每个消息必须发送给指定的接受者,并且消息的解析依赖于接受者。
● 消息传递是一种强大的机制,提供了函数名重载,多态和软件复用的能力。
消息传递的作用
● 是对现实世界的模拟,符合人们自然的思维方法
● 是软件复用的重要手段
五、泛化与多态
泛化(继承)
● 泛化是面向对象方法中的一个重要概念,能够在很大程度上提高软件开发效率。也称继承、一般-特殊结构。
● 泛化关系是一种类之间的关系。可将一类对象进一步细分为许多子类,原来的类(父类)与子类之间的关系就是泛化关系。父类称为子类的泛化,子类称为父类的特化。
多态(Polymorphism)
● 在面向对象方法中,多态主要是指在泛化关系中的各个类中名字相同的属性和操作具有不同的意义。
● 而多态则是为了实现另一个目的——接口复用,节省大量的编码工作量。
覆盖(override)与重载(overload)
● 覆盖,如果子类中的成员函数f(x)具有父类中成员函数f(x)相同的基调(函数的函数名与函数的参数表),那么称子类对父类的f(x)进行了覆盖。
● 重载,是指允许存在多个同名函数,但这些函数的参数表不同(或许参数个数不同,或时许参数类型不同,或许两者都不同),即具有不同的基调(signature)。
● 覆盖导致多态,由动态链接实现。
● 重载与多态无关,由静态链接实现。
基调(signature)与原型(prototype)
● 函数原型
ⓐ 类似函数定义时的函数头。为了能使函数在定义之前就能被调用,C++规定可以先说明函数原型,然后就可以调用函数。函数定义可放在程序后面。
ⓑ 函数原型由函数返回类型、函数名和参数表组成,它与函数定义的返回类型、函数名和参数表必须一致。函数原型不必包含参数的名字,可只包含参数的类型。
ⓒ 例如: int area (int, int ); 等价于 int area(int a,int b);
● 函数基调(signature,签名,特征标记)
ⓐ 函数签名包含了一个函数的信息,包括函数名、参数类型、函数所在类和命名空间及其他信息。具体的函数签名方法视不同的编译器而定,一般不包括函数的返回类型.
ⓑ int f();
ⓒ float f();
ⓓ 不能出现在同一个类中
● 函数调用与函数基调有关
动态链接
● 在运行时才能知道消息的特定接受者及其响应的方法.
● 编译期间不知连接具体的函数地址,运行时链接相关函数地址.
● 动态链接会影响程序的效率
● 纯面向对象语言所有函数都以动态链接方式运行
● C++中可以选择执行哪些函数是虚成员函数
六、关联与聚合
关联
● 同现实世界一样,面向对象方法中的各个对象并不是孤立存在的,它们之间存在各种具有特定含义的关系。
● 关联是对象间链的集合
聚合
● 用来描述对象之间的整体-部分关系
● 整体-部分关系有很多种类