继承有两种用途:
1. 继承基类的方法,而且作出本身的改变或者扩展(代码重用)
2. 申明某个子类兼容于某基类,定义一个接口类interface,接口类定义了一些接口名且未实现接口的功能,子类继承接口类,而且实现接口中的功能java
class Wechat: ''' 微信支付 ''' def pay(self, money): print('已经用微信支付%s元.' % money) class Alipay: ''' 支付宝支付 ''' def pay(self, money): print('已经用支付宝支付%s元.' % money) def pay(pay_obj, money): ''' 支付函数,整体负责支付 对应支付的对象和要支付的金额 ''' pay_obj.pay(money) ali = Alipay() pay(ali, 200)
若是咱们又定义了一个支付类且没有定义pay方法:python
class Wechat: ''' 微信支付 ''' def pay(self, money): print('已经用微信支付%s元.' % money) class Alipay: ''' 支付宝支付 ''' def pay(self, money): print('已经用支付宝支付%s元.' % money) class Applepay: def fuqian(self, money): print('已经用Applepay支付%s元.' % money) def pay(pay_obj, money): ''' 支付函数,整体负责支付 对应支付的对象和要支付的金额 ''' pay_obj.pay(money) # 由于 Applepay 类中未定义 pay 方法 ali = Alipay() pay(ali, 200) apple = Applepay() pay(apple, 300) # 报错
经过上面的例子,报错是由于 Applepay 类中没有定义 pay 方法。在这里咱们能够经过继承的关系来手动抛出异常。微信
class Payment: # 建立一个基类 def pay(self, money): # 基类中包含 pay 方法 raise NotImplemented # 主动抛出异常 class Wechat(Payment): ''' 微信支付 ''' def pay(self, money): print('已经用微信支付%s元.' % money) class Alipay(Payment): ''' 支付宝支付 ''' def pay(self, money): print('已经用支付宝支付%s元.' % money) class Applepay(Payment): def fuqian(self, money): print('已经用Applepay支付%s元.' % money) def pay(pay_obj, money): ''' 支付函数,整体负责支付 对应支付的对象和要支付的金额 ''' pay_obj.pay(money) ali = Alipay() pay(ali, 200) apple = Applepay() pay(apple, 300) # 报错
已知 Applepay 类中没有 pay 方法,则会去基类中寻找,基类中定义的 pay 方法是主动抛出异常。
可使用 abc 模块来实现接口,自动的去检查是否实现了某方法app
from abc import ABC, abstractclassmethod, ABCMeta class Payment(metaclass=ABCMeta): @abstractclassmethod def pay(self, money): raise NotImplemented class Wechat(Payment): ''' 微信支付 ''' def pay(self, money): print('已经用微信支付%s元.' % money) class Alipay(Payment): ''' 支付宝支付 ''' def pay(self, money): print('已经用支付宝支付%s元.' % money) class Applepay(Payment): def fuqian(self, money): print('已经用Applepay支付%s元.' % money) def pay(pay_obj, money): ''' 支付函数,整体负责支付 对应支付的对象和要支付的金额 ''' pay_obj.pay(money) ali = Alipay() pay(ali, 200) apple = Applepay() # 实例化就能检查出子类是否建立了 pay 方法
实践中,单纯的从子类继承父类的意义不大,甚至有害,由于它使得子类与基类出现强耦合。
继承的第二种含义就很是重要,它又叫‘接口继承’
接口继承实质上是要求‘作出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理,实现了特定接口的全部对象’ -- 这在程序设计上,叫作归一化。
归一化使得高层的外部使用者能够不加区分的处理全部接口兼容的对象集合。函数
什么是抽象类:微信支付
与java同样,python也有抽象类的概念可是一样须要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。
为何要有抽象类:
若是说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
好比咱们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,
要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远没法吃到一个叫作水果的东西。
从设计角度去看,若是类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从设计角度去看,若是类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不一样之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。
这一点与接口有点相似,但实际上是不一样的,即将揭晓答案spa
#一切皆文件 import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' pass @abc.abstractmethod #定义抽象方法,无需实现功能 def write(self): '子类必须定义写功能' pass # class Txt(All_file): # pass # # t1=Txt() #报错,子类没有定义抽象方法 class Txt(All_file): #子类继承抽象类,可是必须定义read和write方法 def read(self): print('文本数据的读取方法') def write(self): print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,可是必须定义read和write方法 def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,可是必须定义read和write方法 def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样你们都是被归一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)
抽象类与接口类设计
抽象类的本质仍是类,指的是一组类的类似性包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的类似性。
抽象类是一个介于类和接口直接的一个概念,同时具有类和接口的部分特性,能够用来实现归一化设计
在python中,并无接口类这种东西,即使不经过专门的模块定义接口,咱们也应该有一些基本的概念。code