《Python语言程序设计》学习笔记
笔记选自《Python语言程序设计》[美]梁勇 著
本篇笔记没有记录用python绘画的turtle库
第12章 继承和多态
- 父类和子类
GeometricObject.py
class GeometricObject:
def __init__(self, color="green", filled=True):
self.__color=color
self.__filled=filled
def getColor(self):
return self.__color
def setColor(self, color):
self.__color=color
def isFilled(self):
return self.__filled
def setFilled(self, filled):
self.__filled=filled
def __str__(self):
return "color: "+self.__color+" and filled: "+str(self.__filled)
CircleFromGeometricObject.py
from GeometricObject import GeometricObject
import math
class Circle(GeometricObject):
def __init__(self, radius):
super().__init__()
self.__radius=radius
def getRadius(self):
return self.__radius
def setRadius(self):
self.__radius=radius
def getArea(self):
return self.__radius * self.__radius * math.pi
def getDiameter(self):
return 2 * self.__radius
def getPerimeter(self):
return 2 * self.__radius * math.pi
def printCircle(self):
print(self.__str__() + " radius: "+ str(self.__radius))
Circle类使用下面的语法派生自GeometricObject类
class Circle(GeometricObject):
Circle继承了GeometricObject类,继承了父类中所有可访问的数据域或方法
super().__init__()
调用父类的__init__()
方法,这在创建定义在父类中的数据域是很重要的。
较老语法,也可以使用下面的语句调用父类__init__
方法:
GeometricObject.__init__(self)
不推荐使用。
super()
指向父类。使用super()
来避免显式地指向父类。每当使用super()
来调用一个方法时,不需要传递self
参数。
- 允许多重继承:从几个类派生出一个子类
class Subclass(SuperClass1, SuperClass2, …):
initializer
methods
- 覆盖方法:为了覆盖父类的方法,子类中的方法必须使用与父类方法一样的方法头。子类从父类继承方法。有时,子类需要修改定义在父类中的方法的实现。这称作方法覆盖。
class Circle(GeometricObject):
# Other methods are omitted
# Override the __str__ method defined in GeometricObject
def __str__(self):
return super().__str__()+" radius: "+str(radius)
__str__()
方法在GeometricObject类中定义,在Circle类中修改。在这两个类中定义的该方法都可以在Circle类中使用。要在Circle类中调用定义在GeometricObject中的__str__()
方法,使用super.__str__()
。
在Python中,可以通过在一个方法名前加两条下划线来定义一个私有方法。私有方法不能被覆盖,如果子类中有和父类方法名一样的方法,这两个方法是不相干的,即使这两个方法有相同的方法名。
- object类:
一个类定义时没有指定它的父类,那么它的父类默认是object类。Python中的所有类都派生自object类。
class ClassName:
等同与
class ClassName(object):
object类中定义的所有方法都有两条前导下划线和两条后置下划线。本节主要讨论四个方法,即__new__()
、__init__()
、__str__()
和__eq__(other)
当创建一个对象时,__new__()
方法被自动调用。随后调用__init__()
方法来初始化这个对象。一般你只应该覆盖__init__()
方法来初始化新类中定义的数据域。
__str__()
方法会返回一个描述该对象的字符串,默认返回一个由该对象所属的类名以及该对象十六进制形式的内存地址组成的字符串。通常,应该覆盖这个__str__()
方法。
如果两个对象相等,x.__eq__(x)
返回True,但是,x.__eq__(y)
返回False,虽然x和y有相同的内容,但它们还是两个不同的对象。x.__eq__(y)
与x==y
是等价的。可覆盖这个方法,使两个对象内容相同时返回True。Python的许多像int、float、bool、string和list这样的内置类中,__eq__
方法被覆盖使两个对象内容相同时返回True。
- 多态和动态绑定:
多态是指子类的对象可以传递给需要父类类型的参数。一个方法可以被沿着继承链的几个类执行。运行时由Python决定调用哪个方法,这被称为动态绑定。
面向对象程序设计的三个特点是封装、继承和多态。
继承关系使一个子类继承父类的特征,并且附加一些新特征。子类是它的父类的特殊化;每个子类的实例都是其父类的实例,但是反过来就不成立。例如:每个圆都是一个几何体对象,但并非每个几何体对象都是圆。因此,总可以将子类的实例传给需要父类类型的参数。
动态绑定工作机制如下:假设对象o是类 C 1 C_1 C1、 C 2 C_2 C2、… 、 C n − 1 C_{n-1} Cn−1、 C n C_n Cn的实例,这里的 C 1 C_1 C1是 C 2 C_2 C2的子类, C 2 C_2 C2是 C 3 C_3 C3的子类,…, C n − 1 C_{n-1} Cn−1是 C n C_n Cn的子类。也就是说, C n C_n Cn是最通用的类, C 1 C_1 C1是最特定的类。在Python中 C n C_n Cn是object类。如果对象o调用一个方法p,那么Python会依次在类 C 1 C_1 C1、 C 2 C_2 C2、… 、 C n − 1 C_{n-1} Cn−1、 C n C_n Cn中查找方法p的实现,直到找到为止。一旦找到一个实现,就停止查找然后调用这个第一次找到的实现。
- isinstance函数:判断一个对象是否是一个类的实例。
isinstance(object, ClassName)
如:
isinstance("abc", str) # 返回True
isinstance(12, str) # 返回False
-
类之间的关系:关联、聚合和继承
-
继承:对is-a关系建模
-
关联:是一种常用的二进制关系,可以描述两个类之间的一个动作。例如,一个学生选一门课程就是Student类和Course类之间的一种关联,而一个教员教授一门课程就是Faculty类和Course类之间的一种关联。可以用UML图来表示。
-
聚合和组合:聚合是关联的一种特殊形式,它反映了两个对象之间的归属关系。对has-a关系建模。所有者对象(这里的例子是Student)被称为聚合对象,它的类被称为聚合类。主体对象被称为被聚合对象,它的类被称为被聚合类。一个对象能够被几个其他聚合对象所拥有。如果一个对象是某个聚合对象专门拥有,那么这个对象和它的聚合对象之间的关系被认为是一个组合。
- “一个学生有一个名字”是Student类和Name类的一种组合关系,但是,“一个学生有一个地址”是Student类和Address类的一种聚合关系,因为一个地址可以被多个学生所共有。
- 聚合关系通常在聚集类中表示为一个数据域。
- 聚合可以存在于同一类的实例之间。如“一个人有一名监护人”,都可以用Person类。
-
class Student:
def __init__(self, name, address):
self.name=name
self.address=address
本章总结
- 可以从现有的类派生出新类。这被称为类的继承。新类被称为次类、子类或扩展类。现有类被称为超类、父类或基类、
- 为了覆盖一个方法,必须使用与它的父类中的方法相同的方法名来定义子类中的方法。
- object类是所有Python类的基类。在object类中定义了
__str__()
和__eq__()
方法。 - 多态意味着一个子类对象可以传递给一个需要父类类型的参数。一个方法可能在一条继承链中不同的类中使用。Python决定运行时调用哪个方法。这被称为动态绑定。
- 可以使用isinstance函数测试一个对象是否是一个类的实例。
- 类之间常见的关系是关联、聚合、组合和继承。
关键术语
英文 | 中文 |
---|---|
aggregation | 聚合 |
association | 关联 |
composition | 组合 |
dynamic binding | 动态绑定 |
inheritance | 继承 |
is-a relationships | 是关系 |
multiple inheritance | 多重继承 |
override | 覆盖 |
polymorphism | 多态 |