继承是面向对象的三大特征之一,也是实现代码复用的重要手段。继承经常用于创建和现有类功能类似的新类,又或是新类只需要在现有类基础上添加一些成员(属性和方法),但又不想直接将现有类代码复制给新类。
例如,有一个 Shape 类,该类的 draw() 方法可以在屏幕上画出指定的形状,现在需要创建一个 Rectangle 类,要求此类不但可以在屏幕上画出指定的形状,还可以计算出所画形状的面积。要创建这样的 Rectangle 类,除了将 draw() 方法直接复制到新类中,并添加计算面积的方法,其实还有更简单的方法,即让 Rectangle 类继承 Shape 类,这样当 Rectangle 类对象调用 draw() 方法时,
Python 解释器会自动去 Shape 类中调用该方法,如此,我们只需在 Rectangle 类中添加计算面积的方法即可。
Python 中,实现继承的类称为
子类,被继承的类称为
父类(也可称为
基类、
超类)。子类继承父类的语法是:在定义子类时,将多个父类放在子类之后的圆括号里。语法格式如下:
class 类名(父类1, 父类2, ...):
#类定义部分
注意,Python 的继承是多继承机制,即一个子类可以同时拥有多个直接父类。
从上面的语法格式来看,定义子类的语法非常简单,只需在原来的类定义后增加圆括号,并在圆括号中添加多个父类,即可表明该子类继承了这些父类。如果在定义一个 Python 类时,并未显式指定这个类的直接父类,则这个类默认继承 object 类。
object 类是所有类的父类,要么是直接父类,要么是间接父类。
父类和子类的关系,就好像水果和苹果的关系,苹果是一种特殊的水果,苹果是水果的子类,水果是苹果的父类,因此可以说,苹果继承了水果。不仅如此,由于子类是一种特殊的父类,因此父类包含的范围总比子类包含的范围要大,所以可以认为父类是大类,而子类是小类。
从实际意义上看,子类是对父类的扩展,子类是一种特殊的父类。从这个意义上看,使用继承来描述子类和父类的关系是错误的,用扩展更恰当。因此,这样的说法更加准确:苹果扩展了水果这个类。
从子类的角度来看,子类扩展(extend)了父类;但从父类的角度来看,父类派生(derive)出子类。也就是说,扩展和派生所描述的是同一个动作,只是观察角度不同而已。
下面程序示范了子类继承父类的特点。下面是 Fruit 类的代码:
class Fruit:
def info(self):
print("我是一个水果!重%g克" % self.weight)
class Food:
def taste(self):
print("不同食物的口感不同")
# 定义Apple类,继承了Fruit和Food类
class Apple(Fruit, Food):
pass
# 创建Apple对象
a = Apple()
a.weight = 5.6
# 调用Apple对象的info()方法
a.info()
# 调用Apple对象的taste()方法
a.taste()
运行结果为:
我是一个水果!重5.6克
不同食物的口感不同
上面程序中,定义了两个父类:Fruit 类和 Food 类,接下来定义了一个 Apple 类,该类本身是空类,但其继承自 Food 类和 Fruit 类。因此,在主程序部分创建了 Apple 对象之后,可以访问 Apple 对象的 info() 和 taste() 方法,这表明 Apple 对象也具有了 info() 和 taste() 方法,这就是继承的作用,即子类扩展(继承)了父类,将可以继承得到父类定义的方法,这样子类就可复用父类的方法了。
关于Python的多继承
大部分面向对象的编程语言(除了
C++)都只支持单继承,而不支持多继承,这是由于多继承不仅增加了编程的复杂度,而且很容易导致一些莫名的错误。
Python 虽然在语法上明确支持多继承,但通常推荐如果不是很有必要,则尽量不要使用多继承,而是使用单继承,这样可以保证编程思路更清晰,而且可以避免很多麻烦。
当一个子类有多个直接父类时,该子类会继承得到所有父类的方法,这一点在前面示例中己经做了示范。现在的问题是,如果多个父类中包含了同名的方法,此时会发生什么呢?此时排在前面的父类中的方法会“遮蔽”排在后面的父类中的同名方法。例如如下代码:
class Item:
def info (self):
print("Item中方法:", '这是一个商品')
class Product:
def info (self):
print("Product中方法:", '这是一个工业产品')
class Mouse(Item, Product): # ①
pass
m = Mouse()
m.info()
上面 ① 号代码让 Mouse 继承了 Item 类和 Product 类,由于 Item 排在前面,因此 Item 中定义的方法优先级更好,Python 会优先到 Item 父类中搜寻方法,一旦在 Item 父类中搜寻到目标方法,Python 就不会继续向下搜寻了。
运行上面程序,将看到如下输出结果:
Item 中方法:这是一个商品
如果将程序中第 7 行代码改为如下形式:
class Mouse(Product,Itern): #①
此时 Product 父类的优先级高于 Item 父类,因此 Product 中的 info() 方法将会起作用。运行上面程序,将会看到如下输出结果:
Product中方法:这是一个工业产品
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。