继承与复用
在自定义类型的基本形式中:
ParentClass 是用来进行继承的,被继承的 ParentClass 是父类,定义的 ClassName 是子类。可以认为子类是一种特殊的父类。
例如,假设父类是哺乳动物,人作为一个子类可以继承这个父类,因为人是哺乳动物的一种;狮子也可以继承哺乳动物,因为狮子也是哺乳动物的一种。
类的继承
考虑这样一个表示树叶的类:
继承这个类,生成一个枫树叶类:
构造一个子类对象:
子类会继承父类的属性和方法,父类的属性和方法可以直接调用:
子类虽然没有定义构造函数,但是会直接继承父类的构造函数:
子类额外定义的方法:
方法的重载
子类可以对父类中已有的方法进行重载。例如,在枫树叶类中对.fall()
方法进行重载,即重新定义:
在这个例子中,.fall()
方法被重载,并调用了自定义类中的已有方法。方法定义中的第一个参数 self
表示的就是对象自身,所以可以用 self.change_color()
实现对已有方法的调用:
super () 函数
与父类的.fall () 方法相比,子类的方法只增加了.change_color () 的调用,之后的操作与父类的.fall () 方法一致,代码其实有冗余和浪费。Python 提供了 super()
函数,在子类中调用父类的方法。具体定义如下:
能实现与上面一样的结果:
鸭子类型:一切都是为了复用
鸭子类型(Duck Type)的概念来源于美国诗人詹姆斯・惠特科姆・莱利的诗句:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 在 Python 中,这个概念被衍生为:在使用对象时,可以不关注对象的类型,而关注对象具有的方法或属性;只要对象的属性和方法满足条件,就认为该对象是合法的。
例如,定义这样的一个函数:
这个函数接受一个参数 leaf,并调用它的.fall () 方法。Leaf 类支持.fall () 方法,因此该类型的对象是合法的:
子类 MapleLeaf 也支持.fall () 方法,所以也是合法的对象:
再定义一个类苹果:
在鸭子类型机制下,Python 将函数和方法中的类型检查,变成了接口检查的模式,即 something_fall () 函数不会检查传入的参数 leaf 是什么类型,而是检查 leaf 有没有实现.fall () 接口。