《Python语言程序设计》第十二章学习笔记

《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} Cn1 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} Cn1 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} Cn1 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

在这里插入图片描述

本章总结

  1. 可以从现有的类派生出新类。这被称为类的继承。新类被称为次类、子类或扩展类。现有类被称为超类、父类或基类、
  2. 为了覆盖一个方法,必须使用与它的父类中的方法相同的方法名来定义子类中的方法。
  3. object类是所有Python类的基类。在object类中定义了__str__()__eq__()方法。
  4. 多态意味着一个子类对象可以传递给一个需要父类类型的参数。一个方法可能在一条继承链中不同的类中使用。Python决定运行时调用哪个方法。这被称为动态绑定。
  5. 可以使用isinstance函数测试一个对象是否是一个类的实例。
  6. 类之间常见的关系是关联、聚合、组合和继承。

关键术语

英文中文
aggregation聚合
association关联
composition组合
dynamic binding动态绑定
inheritance继承
is-a relationships是关系
multiple inheritance多重继承
override覆盖
polymorphism多态
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
3. 几何图形(满分50分) 版本1:满分 10 分 设计抽象 GeometricObject 及其子 Triangle 和Circle。 GeometricObject 设计要求如下: ■ 一个名为 colorColor型的私有数据域,表示对象的颜色一个名为 filled 的Boolean型的私有数据域,表示对象是否一个名为 dateCreated 的Date 型的私有数据域,表示对象的 ■ 一个无参构造方法。 ■ 一个能创建特定 color 和filled 的有参构造方法。 ■ 相关数据域的访问器和修改器。 ■ 两个名为 draw 和erase的抽象方法。 ■ 一个名为 getArea的抽象方法。 ■ 一个名为 getPerimeter的抽象方法。 ■ 重写 toString 方法。 Triangle 设计要求如下: ■ 三个名为 side1、side2和 side3 的double 型的私有数据域表 们的默认值是 1.0。要求三个数据域保留 2 位小数。 ■ 一个无参的构造方法创建默认三角形。 ■ 一个能创建带指定 side1、side2和 side3 的有参构造方法。 ■ 所有三个数据域的访问器和修改器方法。 ■ 父抽象方法的实现。 ■ 重写 toString 方法。 Circle 设计要求如下: ■ 一个名为 radius 的double 型的私有数据域,表示圆的半径,数据域保留2 位小数。 ■ 一个名为 PI 的静态常量,其值为 3.14 ■ 一个无参的构造方法创建默认三角形。 ■ 一个能创建带指定 radius 的有参构造方法。 ■ radius 数据域的访问器和修改器方法。 ■ 父抽象方法的实现。 ■ 重写 toString 方法。 测试 TestGeometricObject1 设计要求如下: ■ 一个能随机生成 Circle 和Triangle 对象的静态方法 GeometricObject[] RandomCreateGeometricObject() ■ 以随机生成的数组为参数,输出数组中每个对象的基本信息、周长和面积。 ■ 中其它方法的测试 版本2:满分 20 分 将上面的抽象GeometricObject 改为接口,接口只保留其中四个抽象方法,声明 Circle、Triangle 实现该接口,的基本要求如上,同时为每个增加一个将当前对象序列化 到指定文件的方法 writeToFile(File f)。 测试 TestGeometricObject2 设计要求如下: ■ 一个能随机生成 Circle 和Triangle 对象的静态方法,该方法将随机生成的象序列 化到指定的文件 GeometricObjects.dat 中,序列化成功返回真,否则返回假。 Boolean RandomCreateGeometricObject() ■ 将GeometricObjects.dat 文件中对象全部读出,存储到 GeometricObject 对象数组中, 然后以此数组为参数,输出数组中每个对象的基本信息、周长和面积。 ■ 中其它方法的测试。 新增一个Rectangle ,也实现接口 GeometricObject ,同时修改测试 TestGeometricObject2 ,体会开-闭原则。 版本3:满分 20 分 在第2 步的基础上设计实现一个具有 GUI 界面的几何图形绘制系统系统,要求实现根 据选择的几何图形型来绘制和删除相应的图形,其中相关参数应通过界面输入,并可计算 图形的周长和面积。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值