抽象类
【一】什么是接口
【1】IAnimal.java
- Java 语言中的接口很好的展现了接口的含义: IAnimal.java
- Java的Interface接口的特征
- 是一组功能的集合,而不是一个功能
- 接口的功能用于交互,所有的功能都是public,即别的对象可操作
- 接口只定义函数,但不涉及函数实现
- 这些功能是相关的,都是动物相关的功能,但光合作用就不适宜放到IAnimal里面了
【二】为何要用接口
- 接口提取了一群类共同的函数,可以把接口当做一个函数的集合。
- 然后让子类去实现接口中的函数。
- 这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。
- 归一化的好处
- 归一化让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度
- 归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合
- 就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
- 再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样
【三】模仿interface
【1】继承的两种用途
- 继承基类的方法,并且做出自己的改变或者扩展(代码重用):实践中,继承的这种用途意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
- 声明某个子类兼容于某基类,定义一个接口类(模仿java的Interface),接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
【2】代码演示
# 定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。
class Interface:
# 定接口函数read
def read(self):
pass
# 定义接口函数write
def write(self):
pass
# 文本,具体实现read和write
class Txt(Interface):
def read(self):
print('文本数据的读取方法')
def write(self):
print('文本数据的读取方法')
# 磁盘,具体实现read和write
class Sata(Interface):
def read(self):
print('硬盘数据的读取方法')
def write(self):
print('硬盘数据的读取方法')
class Process(Interface):
def read(self):
print('进程数据的读取方法')
def write(self):
print('进程数据的读取方法')
- 上面的代码只是看起来像接口,其实并没有起到接口的作用,子类完全可以不用去实现接口 ,这就用到了抽象类
【四】什么是抽象类
- 与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
【五】为什么要有抽象类
- 如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
- 比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。
- 从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
- 从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案
【六】在python中实现抽象类
- 只要你这个类继承了我的接口,你就必须给我实现这几个方法
import abc # 利用abc模块实现抽象类
#
#
# # 和 Java的接口一样:我在接口中定义了几个方法
# # 只要你这个类继承了我的接口,你就必须给我实现这几个方法
# # 定义所有文件操作必须实现的方法
class All_file(metaclass=abc.ABCMeta):
all_type = 'file'
# 定义抽象方法,无需实现功能
# abstract : 抽象
@abc.abstractmethod
def read(self):
'子类必须定义读功能'
pass
#
# 定义抽象方法,无需实现功能
@abc.abstractmethod
def write(self):
'子类必须定义写功能'
pass
class Txt(All_file):
def read(self):
...
def write(self):
...
t1 = Txt() # 报错,子类没有定义抽象方法
class DBHandler(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def create_conn(self):
...
@abc.abstractmethod
def read_data(self):
...
@abc.abstractmethod
def write_data(self):
...
# 控制MySQL的类
class MySQLHandler(DBHandler):
# 【1】必须创建连接 --> 127.0.0.1 : 3306
def create_conn(self):
...
# 【2】写入SQL的方法,保存数据
def read_data(self):
...
# 【3】读取SQL的方法,读取数据
def write_data(self):
...
mysql = MySQLHandler()
【七】总结: 抽象类的书写步骤
【1】创建一个父类
【2】必须导入 import abc
【3】父类必须继承一个属性 class Parent(metaclass=abc.ABCMeta):
【4】在想要子类中必须实现的方法上面加一个 装饰器 : @abc.abstractmethod
【5】子类继承父类,子类必须重写父类中被添加 了 @abc.abstractmethod 的方法