接口和抽象类
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)
且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 抽象类 接口类 规范和约束 metaclass指定的是一个元类
@abstractmethod
def pay(self):pass # 抽象方法
class QQ(Payment):
def pay(self,money):
print('您用qq支付了%s元' % money)
def ret(self):
print('支付失败....')
class Ali(Payment):
def pay(self,money):
print('您用支付宝支付了%s元' % money)
class Wechat(Payment):
def pay(self,money):
print('您用微信支付了%s元' % money)
def pay(obj,money):
obj.pay(money) # a1.pay(200)
q1 = QQ()
a1 = Ali()
w1 = Wechat()
# q1 = QQ()
# a1 = Ali()
# pay(q1,100) # 统一化设计
# pay(a1,200)
强制统一规范
# 制定一个类的metaclass是ABCMeta,
# 那么这个类就变成了一个抽象类(接口类)
# 这个类的主要功能就是建立一个规范
# 你要抽象类,制定一个规范,强制其有此方法.
# python没有多态的概念,但是python崇尚鸭子类型.
# 定义变量的方法:
#1,java c# 需要定义 类型. int i= 3
#2,java c# 没有多继承的概念.
# i = 1
# i = 'alex'
# 鸭子类型: 它看着像鸭子,那么他就是鸭子.
# str list tuple
str.index()
s1 = 'alex'
class Str:
def index(self):
pass
class List:
def index(self):
pass
class tuple:
def index(self):
pass
#python中好多不同类但同名的方法不是强制规定,而是约定俗成,像上面这三种类,都同样据有index方法,而且功能相似,
# 则 他们三个互称为鸭子.
封装:
重要:
类整体分类:
#第一部分: 公有静态字段 mind = '有思想...' ,私有静态字段. __level = '高等动物'
#第二部分: 特殊方法(__init__(公有属性,私有属性),__str__...)
# 普通方法 def func(self)
# 私有方法 def __func1(self):
#类方法:
# @classmethod
# def f2(self): pass
# 静态方法:
# @staticmethod # 静态方法
# def f2():pass
#属性:
# @property # 属性
# def hex(self): pass
# 私有成员: 私有静态字段,私有属性,私有方法 在变量前+ __双下划线.
#1,封装 对象的封装.
# class Person:
# def __init__(self,name,age):
# self.name = name
# self.age = age
# p1 = Person('oldboy',1000)
# p2 = Person('alex',10000)
# print(p1.name)
# print(p2.name)
2 封装(私有成员.)
类的结构分析: # class Person: # mind = '有思想...' # 第一部分:所有的公有静态变量,公有静态字段 # __level = '高等动物' # 第一部分:私有静态变量,私有静态字段 # def __init__(self,name,age,sex): # 构造方法 # 第二部分 动态方法,方法(函数) # self.name = name # 公有对象属性 # self.age = age # self.__sex = sex # 私有对象属性 # def func(self): # 第二部分:普通方法 # print(666) # def __func1(self): # 第二部分:私有方法 # print(777) # # @staticmethod # 静态方法 # def f2():pass # # @classmethod # 类方法 # def f2(self): pass # # @property # 属性 # def hex(self):pass
私有静态字段
# class Animal:
# __cloth = '皮毛' # _Animal__cloth
# class Person(Animal):
# mind = '有思想...' # 第一部分:所有的公有静态变量,公有静态字段
# __level = '高等动物' # 第一部分:私有静态变量,私有静态字段 # _Person__level
#
# def __init__(self,name,age): # 构造方法 # 第二部分 动态方法,方法(函数)
# self.name = name # 公有对象属性
# self.age = age
# def func(self):
# print(self.__level)
# print(self._Animal__cloth)
# print(self.__cloth)
# 在类的外面访问: 私有静态字段是访问不到的.
# p1 = Person('alex',1000)
# print(p1.mind)
# print(p1.__level)
# print(Person.__level)
# print(Person.__dict__)
# print(Person._Person__level)
# 可以通过对象._类名__变量名 类名._类名__变量名 可以访问到,但是绝对不要这么访问.
# 在类的内部: 私有静态字段是可以访问
# p1 = Person('alex',1000)
# p1.func()
# 父类的私有静态字段,派生类可否访问? 不可访问.
# p1 = Person('alex',10)
# print(p1.__cloth)
# p1.func()
私有静态字段
# class Animal:
# __cloth = '皮毛' # _Animal__cloth
# class Person(Animal):
# mind = '有思想...' # 第一部分:所有的公有静态变量,公有静态字段
# __level = '高等动物' # 第一部分:私有静态变量,私有静态字段 # _Person__level
#
# def __init__(self,name,age): # 构造方法 # 第二部分 动态方法,方法(函数)
# self.name = name # 公有对象属性
# self.age = age
# def func(self):
# print(self.__level)
# print(self._Animal__cloth)
# print(self.__cloth)
# 在类的外面访问: 私有静态字段是访问不到的.
# p1 = Person('alex',1000)
# print(p1.mind)
# print(p1.__level)
# print(Person.__level)
# print(Person.__dict__)
# print(Person._Person__level)
# 可以通过对象._类名__变量名 类名._类名__变量名 可以访问到,但是绝对不要这么访问.
# 在类的内部: 私有静态字段是可以访问
# p1 = Person('alex',1000)
# p1.func()
# 父类的私有静态字段,派生类可否访问? 不可访问.
# p1 = Person('alex',10)
# print(p1.__cloth)
# p1.func()
类外面访问不到.
# p1 = Person('OLDBOY',1000)
# p1.__func() #
# 类内部可以方法.
# p1 = Person('OLDBOY',1000)
# p1.func1()
# 派生类中也是不能访问的.
# p1.func2()
# 私有属性 也是类外部不能访问,派生类不能访问,只能在类内部访问.
# 总结: 对于私有成员来说,他加载到内存时,都会加上_类名__变量名,所以你在类的外部,或者派生类中都不可访问.
#为什么设置私有成员?
# 有些变量,方法,属性,只在类内部进行使用即可,不便于(不允许)类外部或者派生类去调用.
# class Person:
# def __init__(self,username,password): # 构造方法 # 第二部分 动态方法,方法(函数)
# self.usn = username # 公有对象属性
# self.__pwd = self.__makepassword()
# def __makepassword(self):
# '''复杂的加密过程'''
# new_pwd = self.__pwd + '666'
# return new_pwd
# p1 = Person('alex','123')
# print(p1.__pwd)
两道面试例题
# class A:
# def __init__(self):
# self.__func()
# def __func(self):
# print('IN A')
# class B(A):
# def __func(self):
# print('IN B')
# b1 = B()
class A:
def __init__(self):
self.func()
def func(self):
print('IN A')
class B(A):
def func(self):
print('IN B')
b1 = B()
# print(b1.name)
# print(b1.func)
print(b1.func)
print(b1.func())
实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
接口提取了一群类共同的函数,可以把接口当做一个函数的集合。 然后让子类去实现接口中的函数。 这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。 归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。 比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。 再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样 为什么用接口
接口提取了一群类共同的函数,可以把接口当做一个函数的集合。 然后让子类去实现接口中的函数。 这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。 归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。 比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。 再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样 为什么用接口
抽象类
什么是抽象类
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
为什么要有抽象类
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案
在python中实现抽象类

抽象类与接口类
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。
1.多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
接口隔离原则: 使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
2.方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现