生命个体——面向对象
在前面的章节中,数据和数据的操作是分开进行的,或者说没有一个类似现实世界中的生命体,既具有一些属性特征,又能够执行一定的功能。这对于计算机编程来说,无疑是缺憾的,其所描述世界的方法和世界的特征无法统一在一起。面向对象编程的思想因此而产生,同样在Python中也有面向对象编程。
先来举一个例子,在前面我们提到了关羽,如果再加上张辽、陆逊等,我们可以把他们统称为武将,具体来说,关羽又属于蜀将,张辽为魏将,陆逊为吴将。之所以称为武将,是因为他们具有共同特征,即有武器,会骑马,会武艺且能指挥打仗,当然他们还有一些人的基本特征,如身高、年龄、经验等。可以看出,在这里“人物”“武将”“蜀将”都是类别,是一些具有共同特征的事物的集合,是更为抽象的概念,而每一个将领如关羽、张辽、陆逊都是具体的对象,如图5-1所示。
图5-1 人物类—武将类—蜀将、魏将、吴将
在计算机编程中,我们把这些抽象的类别称为类(class),把这些具体的事物称之为对象(object)。面向对象的编程可以把零散的数据和数据的操作结合成更为有机的整体(封装)。例如,关羽打过一次仗之后,就会增加他自己的经验值。程序语言中的方法、操作对应人的行为、动作,采用函数来实现;而属性等用数据来表示。这样对数据和数据的操作就可以在面向对象编程中实现有机的结合。
因此在面向对象编程中,最核心的就是类和对象。类用来描述具有相同属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。类中需要包含数据成员和方法(类中定义的函数)。类中的数据成员包括了属于类的变量(对象公用的)以及实例变量(定义在方法中的变量,只作用于当前实例的类)。类可以看作一个模板或者模子,由类生成具体的一个个对象。
类与类之间可以构建继承关系,例如,上面的武将和蜀将这两个抽象类别可以构成继承关系,即蜀将类继承了武将类中的数据和方法,此时武将类被称为基类(base class)或父类,蜀将类被称为派生类(derived class)或子类,或者我们也可以称武将类派生出蜀将类,如图5-2所示。
图5-2 继承与派生
在派生类中,可以不用重新编写与基类相同的代码,但如果继承过来的方法不能满足派生类的要求,可以对其进行改写,这称为方法的覆盖(override),也称为方法的重写。这样一来,同一个函数名,当对应的对象不同时,就会执行不同的功能,这就是多态,即“多种形态”。例如,我们有一个多功能启瓶器,虽然它只是一个物品,但是它遇到不同的酒瓶,如葡萄酒、啤酒酒瓶,就会根据瓶子的不同而采用不同的方法来打开。再如,同一个USB接口可以接不同的设备,如U盘、移动硬盘、打印机,但是传输的内容不同,相应的处理方式也会有所不同。图5-3所示为生活中的多态概念。
总之,数据封装、继承和多态是面向对象的三大特点,我们后面会详细讲解。下面将前面涉及的一些名词总结如下。
图5-3 生活中的多态概念
●实例化:创建一个类的实例,即类的具体对象。
●方法:类中定义的函数。
●对象:通过类定义的数据结构实例。对象包括数据成员(类变量和实例变量)和方法。
●数据成员:类变量或者实例变量,用于处理类及其实例对象的相关数据。
●类变量:属于类的变量,在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
●实例变量:定义在方法中的变量,只作用于当前实例的类。
●继承:即一个派生类继承基类的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
●方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写。
下面将介绍如何在Python中创建和使用类与对象。