软件是这样“炼”成的:Java学习全演练
上QQ阅读APP看书,第一时间看更新

1.2 面向对象的核心概念

在面向对象的软件开发过程中,开发者的主要任务就是先建立模拟问题领域的对象模型,然后通过程序代码来实现。关于对象、属性、状态、行为、方法、实现等概念将在本章中学习。

1.2.1 对象

1. 万物皆为对象

不管处于什么样的环境,不管我们处理什么事件人们必须面对许多对象。我们在学习过程中,书本、电脑、我们的同学和我们的老师都是对象;如果我们在踢足球,足球、场地和球门都是对象;如果我们正在吃饭,饭碗、筷子和餐桌都是对象;对象可能是非常小的,例如,分子;对象也可以非常大,例如,宇宙、银河系、亚洲、中国、北京市、北京科技大学等。

2. 对象的属性

对象的属性用于描述对象的状态、特征以及组成部分。

如果对一位学生进行描述的话,可能会涉及的内容包括姓名?性别是男还是女?年龄是少年还是青年?身高是高个子还是矮个子?体重是超重还是标准?血型是A型还是B型?等等。这些描述全是用于描述一位学生的特征的。

有用于描述人的状态的,包括周岁、男或女、30还是40等。

3. 对象的行为

对象的行为也就是对象能够完成的功能,每个对象都会有自己的行为,行为用于改变对象自身的状态,或者向其他对象发送消息,有时候一个行为会同时包含这两者。现在只讨论改变自身状态的行为,关于向其他对象发送消息的行为将在后面讨论。我们以学生为例来研究对象的行为。

每个对象都存在大量的行为。有些行为是可以看到的。学生在整个生活中有学习文化课、考试、吃饭等必要的社会活动。

另外,还有一些行为是作为学生所必需却不被注意的。这些行为包括上课、完成作业、参加考试、完成实验,这些行为是日常的我们却不以为然了,并且这些行为是体现其学生身份的关键所在,也是关系着能否毕业的关键所在。

4. 对象的标识

系统中的每个对象都有自己的标识,这个标识对于系统中的每个对象是唯一的。标识有些是大家熟悉的,例如,专业;有些标识是不熟悉的,例如,学号。但是学号对于学生来说肯定熟悉。因为属于系统的不同的用户,所以关注的对象也不一样。

作为一个程序员,要完成这样一个系统,系统中所有用户关注的信息我们都需要关注。标识也是一个属性。通常标识也是用于描述对象的,这和前面的属性是相同的。标识本身可能有意义,例如,学生的专业名称;其标识本身也可能没有意义,仅仅作为标识,但是,学号仅用于标识一个学生。

5. 对象之间的关系

对象之间的关系包括:

①整体与部分的关系,例如,学生和性别的关系,整体属性是学生,部分属性是性别。

②关联关系,例如,学生洪杨俊是计算机专业的学生。

1)整体与部分的关系

具有这种关系的两个对象之间有比较强的依赖关系,就像某位学生必须有性别属性,如果没有性别这个属性,这个学生就不能被安排住宿,也就是说只要是一个学生,就一定有属于他的性别。

这种关系的对象一旦创建完成之后,都是作为一个整体来使用,通常情况下不会单独考虑组成部分,如果要考虑组成部分也是先考虑整体。例如,要改变这个学生的性别,通常学校会调查是什么原因。但是不管怎样,即使直接说性别,也会有一个前提,就是某人的性别。这种关系一旦建立,通常不再改变。

2)关联关系

关联关系的两个对象之间通常没有依赖关系。就像一个学生在学习过程中就会不停地上学、毕业,这样他/她所上的学校也在不停地变化。学生大学上了北京科技大学,学生和北京科技大学之间的关联关系就建立起来了。关联关系建立之后,学生就按照北京科技大学的相关规定来学习和生活。学生毕业了,学生和北京科技大学这种关联关系就解除了,北京科技大学的相关制度不再会对这位学生产生影响。另外,不像整体与部分的关系,一旦创建基本不再变化,关联关系可以根据需要随时创建,随时解除。

3)关系中的量

一个系有3个专业,一个专业有三个班,一个班有30个学生,这里的数字就是关系中的量。不管是整体与部分的关系,还是关联关系都存在着量。根据关系中的量可以把关系分为一对一、一对多、多对一和多对多4种。

1.2.2 类

具有相同属性(数据元素)和行为(功能)的对象的抽象就是类。例如,学生毕业登记表、学生奖惩记录表。因此,类是经过对象抽象而得到的。类的具体化就是对象,也可以说类的实例是对象

类具有属性,它是对象的状态的抽象,用数据结构来描述类的属性。

类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述。

在客观世界中有若干类,这些类之间有一定的结构关系。通常有两种主要的结构关系,即一般和整体。一般指具体结构,称为分类结构,也可以说是“或”关系,或者是“is a”关系;整体指部分结构,称为组装结构,它们之间的关系是一种“与”关系,或者是“has a”关系。

对象之间进行通信的结构叫做消息。在对象的操作中,当一个消息发送给某个对象时,消息包含接收对象去执行某种操作的信息。发送一条消息至少要包括说明接收消息的对象名、发送给该对象的消息名(即对象名、方法名)。一般还要对参数加以说明,参数可以是认识该消息的对象所知道的变量名,或者是所有对象都知道的全局变量名。类中操作的实现过程叫做方法,一个方法有方法名、参数、方法体。

关于类的详细内容将在后续章节中讲述。

1.2.3 继承

继承是类与类之间的关系,分为父类和子类。在父类和子类之间同时存在着继承和扩展关系。子类继承了父类的属性和方法,同时,子类还可以扩展出新的属性和方法,并且还可以覆盖父类中方法的实现方式。

覆盖是指子类中重新实现父类中的方法。

注意:子类只能继承父类的部分属性和方法。父类中private修饰的属性和方法,对子类是透明的。

继承与扩展同时提高了子系统的可重用性和可扩展性。

继承与扩展导致面向对象的软件开发领域中架构类软件系统的发展。关于类间继承关系将在后续章节中详细说明。

1.2.4 接口

Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征说明,没有方法的实现,接口功能是为其他类提供服务。现实世界中,接口也是实体。在面向对象中,接口是一个抽象的概念,是指系统对外提供的所有服务的定义。

接口描述系统能够提供那些服务,但是不包含服务的实现细节。

对象中所有向使用者公开的方法声明构成了对象的接口。

接口是提高系统松耦合的有力手段。接口还可提高子系统的可扩展性。

(1)概念性接口,即对外提供的所有服务,对象中表现为public类型的方法的声明。

(2)接口类型指用interface关键字定义的实实在在的接口,它用于明确地描述系统对外提供的所有服务,更清晰地把系统的实现细节与接口分离。

1.2.5 封装与透明

1. 封装

封装是指隐藏对象的属性和实现细节,仅对外公开服务。

其优点如下。

①便于正确使用、方便理解,防止使用者错误修改系统的属性和方法。

②有助于建立子系统之间的松耦合关系,提高独立性。

③提高软件的可重用性,每个系统都是一个相对独立的整体。

④降低了构建大型企业系统的风险,即使系统不成功,个别的子系统还是有价值的。

良好的系统会封装所有的实现细节,把它的服务与实现清晰地隔离开来,系统之间只通过接口进行通信。

封装的访问类别如下。

(1)public:最高级别,对外公开。

(2)protected:类本身或者子类公开,即保护级别。

(3)默认:只对同一个包中的类公开,包级别。

(4)private:不对外公开,只能在对象内部访问,级别最低。

到底哪些对象的属性和方法应该公开,哪些应该隐蔽呢?有两大原则:①把尽可能多的方法和属性藏起来,对外提供简洁的接口。②系统的封装程度越高,那么对象独立性就越高,使用也更方便。

将类中的属性尽量地封装起来,把所有的属性藏起来,有以下几个优点。

①更符合真实世界中外因通过内因起作用的客观规律。

②能够灵活地控制属性的读和修改访问级别。

③防止使用者错误地修改属性。

④有助于对象封装实现细节。

2. 透明

与封装具有相同含义的一个概念就是透明,对象实现细节,也就意味着对使用者是透明的。

1.2.6 多态

多态是指多个方法只能有一个名称,但可以有许多形态,也就是程序中可以定义多个同名的方法,用“一个接口,多个方法”来描述。可以通过方法的参数和类型引用。例如,人们喜欢说一句话“想死人了”,这句话本身的应用场景不一样其含义就不一样了。如果这句话用于亲人之间,表达的是一种思念之情;如果用于两个敌对仇人之间,就是表达对对方的恐吓。多态其实就是方法名相同,参数不同。以上不同的参数就是敌对仇人和亲人两个不同的参数。

在Java语言中,多态性体现在两个方面,即由方法重载实现的静态多态性(编译时多态)和方法重写实现的动态多态性(运行时多态)。

1. 编译时多态

在编译阶段,具体调用哪个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。

2. 运行时多态

由于子类继承了父类所有的属性(私有的除外),所以子类对象可以作为父类对象使用。程序中凡是使用父类对象的地方,都可以用子类对象来代替。一个对象可以通过引用子类的实例来调用子类的方法。

1.2.7 组合

组合是一种用多个简单子系统来组装出复杂系统的有效手段。

对于一个组合系统,用UML语言描述。组合系统与它的子系统之间为聚集关系,子系统之间则存在关联关系或依赖关系。

1.2.8 绑定

绑定指的是将一个过程调用与相应代码链接起来的行为。动态绑定是指与给定的过程调用相关联的代码只有在运行期才可知的一种绑定,它是多态实现的具体形式。

1.2.9 消息

对象之间需要相互沟通,沟通的途径就是对象之间收发信息。消息内容包括接收消息的对象的标识,需要调用的函数的标识,以及必要的信息。消息传递的概念使得对现实世界的描述更容易。