类的继承核心是代码的复用和程序功能高度的扩展性。继承可以直接实现代码的复用,功能的扩展性是指继承后的派生类在父类的基础上增加新的行为,或者对父类的行为进行扩展。
认识类的多态性
案例1:派生类在父类的基础上增加新的行为
在『类的继承』一课中,给出了一个案例,案例内容及案例代码参见『类的继承』一课。案例中类继承结构如下图所示:

图中的纸质图书类,电子图书类、视频类和音频类均继承于Product类,被继承的Product称为父类,继承的纸质图书类,电子图书类、视频类和音频类称为派生类(子类),派生类继承父类的所有属性和方法。
现在要求PaperBook类除了输出Product类的公有属性外,还要输出PaperBook类的私有属性。从案例代码中可以看出,PaperBook类的父类提供了输出公有属性的行为,下面是Product类和PaperBook类的代码:
#定义Product类
class Product(object):
#构造方法
def __init__(self,name,price,author,summary):
self.name = name
self.price = price
self.author = author
self.summary = summary
#输出产品属性
def outProduct(self):
print("产品名称:%s" % (self.name))
print("产品价格:%f" % (self.price))
print("产品作者:%s" % (self.author))
print("产品摘要:%s" % (self.summary))
#定义图书类,图书类继承于Product类
class PaperBook(Product):
#构造方法
def __init__(self,name,price,author,summary,words,pageNumbers):
Product.__init__(self,name,price,author,summary)
self.words = words
self.pageNumbers = pageNumbers
book = PaperBook("Pyhton编程基础",39.9,"Jack","Python编程基础知识","120千字","320页")
book.outProduct()
下面是案例代码的执行结果:
=== RESTART: D:/pythoncode/case12.py ===
产品名称:Pyhton编程基础
产品价格:39.900000
产品作者:Jack
产品摘要:Python编程基础知识
>>>
PaperBook类虽然可以调用父类的outProduct()方法输出公有属性,但无法输出PaperBook类的私有属性。这种情况下,可以在PaperBook类增加outPaperBook()方法,用于输出PaperBook类的私有属性,代码如下:
def outPaperBook(self):
self.outProduct();
print("图书字数:%s" % (self.words))
print("图书页数:%s" % (self.pageNumbers))
outPaperBook()方法首先调用父类的outProduct()方法输出公有属性,然后再输出该类的私有属性。
修改案例程序代码:
book = PaperBook("Pyhton编程基础",39.9,"Jack","Python编程基础知识","120千字","320页")
book.outPaperBook()
book对象调用outPaperBook()方法,不再调用父类的outProduct()方法。程序执行结果如下所示:
=======RESTART:D:/pythoncode/case12.py=======
产品名称:Pyhton编程基础
产品价格:39.900000
产品作者:Jack
产品摘要:Python编程基础知识
图书字数:120千字
图书页数:320页
>>>
案例2:派生类扩展父类的行为
案例1要求PaperBook类除了输出父类Product类的公有属性外,还要求输出PaperBook类的私有属性。
案例1给出的解决方案是在PaperBook类增加outPaperBook ()方法,该方法首先调用父类的outProduct()方法输出父类的公有属性,然后再输出PaperBook类的私有属性。
其实,还有一种解决方案,在PaperBook类中重写父类的outProduct(),这样当PaperBook对象调用outProduct()方法时,其父类的outProduct()方法被忽略,而执行PaperBook类的outProduct()方法。代码如下:
#定义Product类
class Product(object):
#构造方法
def __init__(self,name,price,author,summary):
self.name = name
self.price = price
self.author = author
self.summary = summary
#输出产品属性
def outProduct(self):
print("产品名称:%s" % (self.name))
print("产品价格:%f" % (self.price))
print("产品作者:%s" % (self.author))
print("产品摘要:%s" % (self.summary))
#定义图书类,图书类继承于Product类
class PaperBook(Product):
#构造方法
def __init__(self,name,price,author,summary,words,pageNumbers):
Product.__init__(self,name,price,author,summary)
self.words = words
self.pageNumbers = pageNumbers
def outPaperBook(self):
self.outProduct();
print("图书字数:%s" % (self.words))
print("图书页数:%s" % (self.pageNumbers))
#重写父类的outProduct方法
def outProduct(self):
print("图书名称:%s" % (self.name))
print("图书价格:%f" % (self.price))
print("图书作者:%s" % (self.author))
print("图书摘要:%s" % (self.summary))
print("图书字数:%s" % (self.words))
print("图书页数:%s" % (self.pageNumbers))
book = PaperBook("Pyhton编程基础",39.9,"Jack","Python编程基础知识","120千字","320页")
book.outProduct()
程序执行结果如下所示:
========RESTART:D:/pythoncode/case12.py========
图书名称:Pyhton编程基础
图书价格:39.900000
图书作者:Jack
图书摘要:Python编程基础知识
图书字数:120千字
图书页数:320页
>>>
案例2给出的派生类重写父类的方法,就是面向对象的多态概念。
在程序运行过程中,派生类的行为代替了父类的行为。父类Product类有输出属性的方法outProduct(),而它的派生类PaerBook类也有这个方法。Python解释器会根据不同的对象实例调用相对应的方法。
如果在派生类中定义某方法与其父类有相同的名称和参数,就称为方法的重写,方法重写是父类与派生类之间多态性的一种表现。
多态是面向对象编程的一大特征,利用多态特征编程,可以让应用程序具有良好的扩展性。通过派生类对父类方法的重写,可以在不改变原有代码的情况下扩展程序的功能。
pass语句
有时基类定义的方法需要派生类来实现,这类方法称为空方法,空方法即定义的方法没有任何要实际执行的语句。
如何定义一个空的方法呢?这就要用到Python提供的pass语句了。
pass语句 是一个空操作,当它被执行时,什么都不发生。 它适合当语法上需要一条语句但并不需要执行任何代码时用来临时占位。
例如定义一个空的方法:
def method():
pass
定义的method()方法没有任何要实际执行的语句,也可以使用pass语句也可以定义一个空类。
class CName:
pass
定义的CName类没有任何内容。也可以用来定义一个空函数。
def functionname():
pass
定义的functionname()函数没有任何要实际执行的语句。