Python面向对象编程(Object Oriented Programming,OOP)之接口类(Interface Class)

引入

在研究这个问题之前,我们先了解一下继承的用途:

  1. 继承基类的方法,并且做出自己的改变或者扩展(代码重用);
  2. 声明某个子类兼容于某个基类,定义一个借口类Interface,借口中定义了一些接口名(函数名),且并未实现接口的功能,由子类实现这个接口中的功能。

接口属于一个特殊的类,里面声明方法,不实现具体功能。

下面演示接口类的基本操作:

一、这样不好,我想要统一一下支付规则:

class QQpay:
    def pay(self, money):
        print("使用QQ支付了%s元" % money)


class Alipay:
    def pay(self, money):
        print("使用支付宝支付%s元" % money)


a = Alipay()
a.pay(100)

b = QQpay()
b.pay(200)

结果:

使用支付宝支付100元
使用QQ支付了200元

Process finished with exit code 0

二、统一支付的规则,归一化设计,统一pay接口:

class QQpay:
    def pay(self, money):
        print("使用QQ支付了%s元" % money)


class Alipay:
    def pay(self, money):
        print("使用支付宝支付%s元" % money)


def pay(obj, money):
    obj.pay(money)


a = Alipay()
b = QQpay()

pay(a, 100)
pay(b, 200)

结果:

使用支付宝支付100元
使用QQ支付了200元

Process finished with exit code 0

三、但是,如果你的代码要给别人操作,他不懂这个规则,就会出问题:

class QQpay:
    def pay(self, money):
        print("使用QQ支付了%s元" % money)


class Alipay:
    def pay(self, money):
        print("使用支付宝支付%s元" % money)


class WeChatPay:
    def fuqian(self, money):
        print("使用微信支付%s元" % money)


def pay(obj, money):
    obj.pay(money)


a = Alipay()
b = QQpay()

pay(a, 100)
pay(b, 200)

c = WeChatPay()
c.fuqian(300)

结果:

使用支付宝支付100元
使用QQ支付了200元
使用微信支付300元

Process finished with exit code 0

四、解决方法:定义一个父类,什么也不写,只是要求继承我的所有类有一个pay方法,这样就制定了一个规范,这种“什么也不写”的类称之为接口类,后者重写的类称为抽象类:

class Payment:
    def pay(self): pass


class QQpay(Payment):
    def pay(self, money):
        print("使用QQ支付%s元" % money)


class Alipay(Payment):
    def pay(self, money):
        print("使用支付宝支付%s元" % money)


class WeChatpay(Payment):
    def fuqian(self, money):
        print("使用微信支付%s元" % money)


def pay(obj, money):
    obj.pay(money)


a = Alipay()
b = QQpay()

pay(a, 100)
pay(b, 200)

c = WeChatpay()
c.fuqian(300)

结果:

使用支付宝支付100元
使用QQ支付200元
使用微信支付300元

Process finished with exit code 0

五、别人在接手你的代码的时候,还是自己写了自己的方法,不知道这些类都继承了同一个类,所以你需要制定一个规范,强制其执行:

# 创建一个规范
from abc import ABCMeta, abstractmethod


class Payment(metaclass=ABCMeta):  # 抽象类 接口类  规范和约束  metaclass指定的是一个元类
    @abstractmethod
    def pay(self): pass  # 抽象方法


class Alipay(Payment):
    def pay(self, money):
        print('使用支付宝支付了%s元' % money)


class QQpay(Payment):
    def pay(self, money):
        print('使用qq支付了%s元' % money)


class Wechatpay(Payment):
    # def pay(self,money):
    #     print('使用微信支付了%s元'%money)
    def recharge(self): pass


def pay(a, money):
    a.pay(money)


a = Alipay()
a.pay(100)
pay(a, 100)  # 归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能
b = QQpay()
b.pay(200)
pay(b, 200)
c = Wechatpay()
pay(c, 300)  # 到用的时候才会报错

# 抽象类和接口类做的事情 :建立规范
# 制定一个类的metaclass是ABCMeta,
# 那么这个类就变成了一个抽象类(接口类)
# 这个类的主要功能就是建立一个规范

结果:

使用支付宝支付了100元
使用支付宝支付了100元
使用qq支付了200元
使用qq支付了200元
Traceback (most recent call last):
  File "D:/Zhenxian/Python/Day18/Basic.py", line 281, in <module>
    c = Wechatpay()
TypeError: Can't instantiate abstract class Wechatpay with abstract methods pay

Process finished with exit code 1

我们再调用pay(c ,300)时发生了错误,也就是说当操作不按照规范进行时将报错。

实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。

继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。

归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。

依赖倒置原则: 高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程

在python中根本就没有一个叫做interface的关键字,上面的代码只是看起来像接口,其实并没有起到接口的作用,子类完全可以不用去实现接口。

猜你喜欢

转载自blog.csdn.net/qq_33567641/article/details/81205298