接口类 抽象类 多态和鸭子类型

一.接口类

1.接口类的定义:

接口类就是一个规范,在python里没有接口类这种数据类型,没有接口类专门的语法
但是 可以通过继承和abc模块实现接口的功能

2.接口类的应用

归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合

2.1利用函数实现支付功能

class WeChatPay:
    def pay(self,money):
        print('通过微信支付了%s元钱'%(money))
class AliPay:
    def pay(self,money):
        print('通过支付宝支付了%s元钱'%(money))
def pay(obj_pay,money):  # 程序的归一化设计
    obj_pay.pay(money)
pay(WeChatPay(),2000)  #通过微信支付了2000元钱
View Code

2.2如果类中方法名和函数支付名不一样就会报错

class WeChatPay:
    def fuqian(self,money):
        print('通过微信支付了%s元钱'%(money))
def pay(obj_pay,money):
    obj_pay.pay(money)
pay(WeChatPay(),2000)   #AttributeError 属性错误
View Code

2.3接口初成:在调用的时候判断 手动报异常:NotImplementedError来解决开发中遇到的问题

payment定了一个规范,如果类中的方法不是按照规定的格式写的,就会执行payment中的报错
class Payment:
    def pay(self,moneyt):    #payment就成了接口类
        raise AttributeError
class WeChatPay(Payment):
    def fuqian(self,money):
        print('通过微信支付了%s元钱'%(money))
p = WeChatPay()
def pay(obj_pay,money):
    obj_pay.pay(money)
pay(p,2000)   #AttributeError
在实例化的时候正常实例化,在执行类中的支付时,找不到pay这个方法,就会到父类中找pay这个方法
View Code

2.4借用abc模块来实现接口 在实例化的时候就会判断是否符合标准

rom abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):   Payment就成了接口类
    @abstractmethod
    def pay(self,moneyt):pass
class WeChatPay(Payment):
    def fuqian(self,money):
        print('通过微信支付了%s元钱'%(money))
p = WeChatPay()  #TypeError:
View Code

二.接口隔离原则

1.接口隔离原则:

使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。

三.抽象类

1.抽象类的概念:

抽象类是规范一个类的类,在python里抽象类和接口类没区别
它的特殊之处在于只能被继承,不能被实例化
2.python是有抽象类的概念。但没有接口类的概念
3.从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
4.抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。
5.接口类和抽象类在java中:
1.接口类:java的接口规定里面的方法一定不能实现(一句代码也不能写)
抽象类:一定是单继承
2.如果发生多继承 那么一定是接口类 且里面的方法都不能实现
如果在方法里有了实现 那么一定是单继承的抽象类
3.无论接口类 还是抽象类 其实都是一种面向对象编程的开发规范
只是在接口类或者抽象类中 去约束继承它的子类必须实现某些方法
6.接口类和抽象类在python中:
1.对于python来说 就没有这些约束:(即可以发生多继承,又可以实现接口里的方法)
因为python没有接口的概念
对于类的继承 没有多继承的限制
2.实际上abc模块是帮我们实现抽象类的方法,只是我们用它来模仿接口类的效果了
3.在python中,只要metaclass = ABCMeta 定义了抽象方法(@abctractmethod)
这个类就不能被实例化。你可以说他是一个抽象类
from abc import ABCMeta,abstractmethod
class File(metaclass=ABCMeta):
    @abstractmethod
    def read(self):
        f = open('file','r')
        self.f = f
    @abstractmethod
    def write(self):
        f = open('file','w')
class Word(File):
    def read(self):
        super().read()
        self.f.read()
        self.f.close()
class PPT(File):
    def read(self):
        super().read()
        self.f.readpicture()
        self.f.close()
View Code

抽象类和接口类总结

1.python是有抽象类的概念。但没有接口类的概念
2.方法的实现:
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
3.多继承问题:
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
接口隔离原则:
使用多个专门的接口,而不使用单一的总接口
View Code

四.多态和鸭子类型

1.多态的概念:python是自带多态的多态指的是一类事物有多种形态。动物有多种形态:人,狗,猪。

java中的多态:在某些强数据语言类型中,归一化设计(在函数参数的问题上)需要传递参数的数据类型
为了几个类的对象都可以作为参数传递给函数,就给这几个类创建一个父类,这样的话让这个父类成为参数的数据类型
子类所有的对象都能作为参数传递了
在python中,传递参数时是弱数据类型特征,不需要指定参数的数据类型

2.多态性:

peo=People()
dog=Dog()
pig=Pig()
#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()
#更进一步,我们可以定义一个统一的接口来使用
def func(obj):
    obj.talk()
View Code

3.多态实例

在java中。如果建立规范 那么必须通过继承抽象类的形式强制约束。
from abc import ABCMeta , abstractmethod
class 序列(metaclass=ABCMeta):
    @abstractmethod
    def index(self):pass
    @abstractmethod
    def slice(self):pass
    @abstractmethod
    def len(self):pass
#list,Tuple,Str是序列表现出来的多种状态
#这就是多态  java崇尚
class List(序列):
    def index(self):
        pass
    def slice(self):
        pass
    def length(self):
        pass
    def append(self):
        pass
class Tuple(序列):
    def index(self):
        pass
    def slice(self):
        pass
    def len(self):
        pass
class Str(序列):
    def index(self):
        pass
    def slice(self):
        pass
    def len(self):
        pass
    def split(self):
        pass
l = List()
t = Tuple()
l.len()
# def len(序列 obj):  在java中必须加数据类型,这也是必须通过继承抽象类的形式强制约束的原因
#     return obj.len()
View Code

4.鸭子类型

多个有相似特征的数据类型之间,不通过建立继承关系,而通过一种约定俗成的制度来约定
list,Tuple,Str看起来像序列,就当他是序列
class List:
    def index(self):
        pass
    def slice(self):
        pass
    def append(self):
        pass
class Tuple:
    def index(self):
        pass
    def slice(self):
        pass
    def len(self):
        pass
class Str:
    def index(self):
        pass
    def len(self):
        pass
    def split(self):
        pass
l = List()
t = Tuple()
s = Str()
l.len()  # 方法
def len(obj):
    return obj.len()
View Code
 
 
 
 
原文地址:https://www.cnblogs.com/zgf-666/p/8530689.html