学习目标:理解面向对象的编程思想,掌握事物抽象为类及封装方法。
面向对象的编程思想
当前软件开发领域有两大编程思想,一个是面向过程的编程思想,一个是面向对象的编程思想。依据编程思想的不同,编程语言也分为面向过程的语言和面向对象的语言。Java、NET等是面向对象的语言,C语言、Fortran等是面向过程的语言。
面向过程的编程思想在考虑问题时,是以一个具体的流程为单位,考虑程序的实现方法,关心的是功能的实现。分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
例如设计一个五子棋程序,面向过程的设计思路是首先分析问题的步骤:
1、开始游戏;
2、黑子先走;
3、绘制画面;
4、判断输赢;
5、轮到白子;
6、绘制画面;
7、判断输赢;
8、返回步骤2;
9、输出最后结果。
把上面每个步骤分别用函数来实现,问题就解决了。面向过程的设计思想,每一个环节只关注行为动作和功能实现,没有考虑数据的状态,而且各个行为之间的耦合性比较强,不利于程序的扩展和模块化。
面向对象的编程思想在考虑问题时,以具体的事物(对象)为单位,考虑它的属性(特性)及动作(行为),关注整体,就好比观察一个人一样,不仅要关注他怎样说话,怎样走路,还要关注他的身高、体重、长相等属性特征。
同样是设计五子棋程序,面向对象的设计则是以事物(对象)的思路来解决问题。
整个五子棋可以分为:
1、玩家对象,这两方的行为是一模一样的;
2、棋盘对象,负责绘制画面;
3、控制对象,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(控制对象)来对棋局进行判定。

面向对象的编程思想更加接近于现实的事物,从现实中抽象出的(事物)对象自身是内聚的,对象有自身的数据(属性)和操作(行为),因此面向对象可以更好地实现开闭原则,即程序对外扩展是开放的,对内修改是关闭的,当程序的需求改变时,可以对模块进行扩展,使其具有满足那些改变的新行为,而无需改动原有的代码。
总的说来,面向对象的设计思想有如下特点:
(1)可扩展:新特性能够很容易的添加到现有系统中,不会影响原有的代码。
(2)可修改:当修改某一部分的代码时,不会影响到其它不相关的部分。
(3)可替代:将系统中某部分的代码用其它有相同接口的类替换时,不会影响到现有系统。
面向对象的编程思想是目前应用最广泛的编程思想,使用面向对象的编程思想适用于规模较大的应用程序。Java面向对象的编程思想引入了许多概念和机制,归纳总结为抽象、封装、继承和多态。采用面向对象的编程思想并不是全部弃用面向过程的编程思想,相对而言,面向过程的编程思想是面向对象编程的基础,面向对象编程的程序里面一定有面向过程的程序片段。在程序中,面向过程的编程思想,通过方法来实现,面向对象的编程思想通过类来封装方法和数据。
抽象与类
面向对象编程思想的一个基本方法就是抽象。抽象是从众多的同类事物中抽取出具有共同特征的过程及方法。
例如:苹果、香蕉、葡萄等都属于水果类别,假如我们要给水果找出共同特点,就需要抽取(抽象)苹果、香蕉、葡萄的共同特征,舍弃其不同的特征。一般说来苹果、香蕉、葡萄都具有汁液多、糖分多、并且还含有挥发性芳香物质、可以生食等特点。具备上述特点的一般都可以归类为水果。

抽象就是对同类事物的概括和归纳,前面例子的苹果、香蕉、葡萄是现实中的事物,人们在品尝的同时,抽取它们共有的特点,并起了一个新名称水果,来概括和归纳具有苹果、香蕉、葡萄共同特点的所有事物。例如:生梨、桃子也具备苹果、香蕉、葡萄的共同特点,因此生梨和桃子也可以归类为水果。
如果以面向对象的编程思想来看前面例子的话,水果可以称之为类,而苹果、香蕉、葡萄可以称之为类的实例或对象。类是抽象出来的事物,现实生活中并不存在,例如水果,水果是人们赋予具有苹果、香蕉、葡萄等共同特点的名称,不单指某一事物;对象是指具体的实物或概念,例如苹果、香蕉、葡萄等对象是实物,而一项政策可能就是一个概念性的对象了,在现实生活中,万事万物皆对象,面向对象编程就是模拟现实生活中的一个个对象来编程的。
现在生活中的许多对象都要进行分类,例如:人类、水果类、动物类、汽车类等。
分类的作用主要是为了便于管理和维护。面向对象的编程思想主要是通过模拟现实世界的各个对象来编程的,那么这些现实世界中的对象是怎样模拟或映射到计算机中的呢?这就要归功与面向对象编程思想的基本方法——抽象。
抽象并不是Java语言中所特有的概念,在其它面向对象的语言中,如C++在构建对象时也需要抽象建模。例如:在学生信息管理系统中,需要将学生的共同特征抽取出来,如学号、学分、性别等特征,构建学生模型。提炼学生共同特征的过程就是抽象建模。通过抽象,可以很容易地归纳出事物的共同特征和行为,以便与其它对象区别开来,这样抽取出来的特征和行为在面向对象的编程中叫做属性和方法。
属性是指对象具有的各种特征,学号、 学分、性别等特征就是学生对象的属性;行为一般用动词描述对象的各种操作。
每个对象的属性都有特定值。由下图可知,学生甲乙和学生丙丁的学号、学分、性别都不一样。

事物抽象的过程也是一个裁剪的过程,事物不同的、非本质性的特征被裁剪掉,留下共同特征。但共同特征也是相对的,例如,对于汽车和大米,从买卖的角度看都是商品,都有价格,是他们的共同的特征,但从其应用方面来看是不同的。所以在抽象时,同与不同,决定于从什么角度上来抽象,抽象的角度取决于分析问题的目的。
类的封装
前面讲到了抽象与对象,抽象是把同类事物的共同特征抽取出来归纳为类,类的具体实例为对象。例如:把具有汁液多、糖分多、含有挥发性芳香物质、可以生食等特征的事物归纳为水果类,苹果、葡萄、生梨则为水果类的具体实例对象。
在面向对象编程思想中,不仅把汁液多、糖分多、含有挥发性芳香物质、可以生食等的共同特征放到水果类里,同时也把水果的开花、落果、膨大、成熟等共同行为放到水果类里,这样水果类既包含了水果所具备的共同特征,也包含了开花、落果、膨大、成熟等共同行为。
类是对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类,水果类具有所有水果的共同属性和行为。类的结构如下图所示:

在Java语言中,类的属性是以成员变量的形式定义的,类的行为是以方法形式定义的。类定义完成后,要在程序中使用类,还需要把类实例化为对象才能使用。
类的封装就是把现实世界同类事物的共同特征和行为抽取出来,放到一个新建的类中,并设置类属性(特征)和行为的访问权限,同时提供外部访问类属性和行为的方法。
把事物的属性和行为封装在一起,可以对外隐藏内部数据,控制用户对内部数据的修改和访问,封装也消除了面向过程编程中数据与操作分离所带来的种种问题,提高了程序的可复用性和可维护性。
下面以水果类为案例,具体说明类封装的过程。
案例1:封装水果类
在Punit5项目unit包下创建Fruits类。代码如下:
package unit;
public class Fruits {
//水果类汁液含量属性
private String water;
//水果类糖分含量属性
private String sugar;
//水果类芳香度属性
private String fragrance;
//水果类的构造方法
Fruits(String inwater,String sugar,String fragrance)
{
this.water = inwater;
this.sugar = sugar;
this.fragrance = fragrance;
}
// 水果类的开花行为
public void flower()
{
System.out.println("开花");
}
// 水果类的成熟行为
public void ripe()
{
System.out.println("成熟");
}
// 水果类的落果行为
public void drop ()
{
System.out.println("落果");
}
}
Fruits类有三个成员变量,这三个成员变量分别对应水果类的三个属性。Water成员变量对应水果类的汁液含量属性;sugar成员变量对应水果类的糖分含量属性;fragrance成员变量对应水果类的芳香度属性。
Fruits类也提供了三个方法,分别对应水果类的三个行为。flower()方法对应水果类的开花行为;ripe()方法对应水果类的成熟行为;drop()方法对应水果类的落果行为。这三个方法也称为成员方法。
与类名相同的Fruits()方法是类的构造方法,当实例化类时,该构造方法会被自动调用。
代码中的public、private是类访问权限修饰符,用来限定外部对类、类成员变量、类成员方法的访问权限。
关于类的成员变量、成员方法、构造方法、访问权限等内容在后面的课中会详细讲述。