接口类和抽象类
时间:2019-06-11
本文章向大家介绍接口类和抽象类,主要包括接口类和抽象类使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
接口类和抽象类(都是一种思想概念)
一、简单的说明什么是接口类和抽象类
Java主要是面向对象编程的,比较推崇设计模式,而接口是在设计模式里面的一种思维概念,所以接口类是Java里面原生支持的,而python中原生不支持接口类,但是由于设计模式里面有接口类这个概念,而python也会用到设计模式的思维,所以也会接触到接口类。
接口类:python原生不支持
抽象类:python原生支持
二、在代码里面实现接口类
定义几种支付方式,并且最后统一支付入口,代码如下:
class Wechatpay: def pay(self,money): print('已经使用微信支付了%s元' % money) class Alipay: def pay(self,money): print('已经使用支付宝支付了%s元' % money) # 再定义一个Applepay类 class Aapplepay: def fuqian(self,money): # 这里不是使用pay函数 print('已经使用苹果支付了%s元' % money) def pay(pay_obj,money): # 统一支付入口,不管使用哪种方式,主要就是支付就可以了 pay_obj.pay(money) wechat = Wechatpay() # 实例化 ali = Alipay() # 实例化 app = Aapplepay() # 实例化 pay(wechat,100) # 通过微信支付100 pay(ali,200) # 通过支付宝支付200 pay(app,300) # 这里调用pay函数,但是前面Applepay里面使用的不是pay函数而是fuqian,所以这里结果将会报错
运行结果:
C:\Users\sku1-1\PycharmProjects\untitled\venv\Scripts\python.exe C:/Users/sku1-1/PycharmProjects/untitled/学习笔记/接口类和抽象类.py 已经使用微信支付了100元 已经使用支付宝支付了200元 Traceback (most recent call last): File "<encoding error>", line 26, in <module> File "<encoding error>", line 16, in pay AttributeError: 'Aapplepay' object has no attribute 'pay'
从上面的运行结果可以知道,定义的第三种支付方式,通过统一支付入口后将无法支付,结果就会报错,改变一下报错的方式,如下代码:
# 再定义一个类 class Payment: def pay(self,money): raise NotImplementedError # 报没有实现这个方法的错误,所以可以知道前面错误的地方就应该存在与pay同名的方法 class Wechatpay(Payment): # 继承Payment类,但是先找自己里面是否有pay函数,有就用自己的,没有才找父类 def pay(self,money): print('已经使用微信支付了%s元' % money) class Alipay(Payment): def pay(self,money): # 继承Payment类,但是先找自己里面是否有pay函数,有就用自己的,没有才找父类 print('已经使用支付宝支付了%s元' % money) # 再定义一个Applepay类 class Aapplepay(Payment): # 继承Payment类,但是先找自己里面是否有pay函数,有就用自己的,没有才找父类,因为这里面没有pay函数, # 所以执行父类,所以最后将会报’NotImplementedError‘的错误 def fuqian(self,money): # 这里不是使用pay函数 print('已经使用苹果支付了%s元' % money) def pay(pay_obj,money): # 统一支付入口,不管使用哪种方式,主要就是支付就可以了 pay_obj.pay(money) wechat = Wechatpay() # 实例化 ali = Alipay() # 实例化 app = Aapplepay() # 实例化 pay(wechat,100) # 通过微信支付100 pay(ali,200) # 通过支付宝支付200 pay(app,300) # 这里调用pay函数,但是前面Applepay里面使用的不是pay函数而是fuqian,所以这里结果将会报错
运行结果:
已经使用微信支付了100元 Traceback (most recent call last): 已经使用支付宝支付了200元 File "<encoding error>", line 33, in <module> File "<encoding error>", line 23, in pay File "<encoding error>", line 4, in pay NotImplementedError
从代码中可以看到,只要你支付方式里面不存在pay的函数方法,就会直接执行父类payment里面的pay方法,从而后面直接报自己写的错误,这样可以提示出错的支付方式里面应该存在
与父类中的pay方法一样的方法或者函数,但是这样的报错方法必须要通过调用pay方法后才能找出错误,如果要在不对pay方法进行调用的情况下就可以找到错误的地方,这样的代码改进如下:
from abc import abstractmethod,ABCMeta class Payment(metaclass=ABCMeta): # 默认的元类type @abstractmethod def pay(self,money): pass # 只要使用了以上这样的方法就表明已经建立一个规范,规范下面所有的代码,使得以下的代码都应该存在与pay同名的方法, # 不存在就无法进行,就会报错,而且报错方法还会具体指出错误所在 class Wechatpay(Payment): # 继承Payment类,但是先找自己里面是否有pay函数,有就用自己的,没有才找父类 def pay(self,money): print('已经使用微信支付了%s元' % money) class Alipay(Payment): def pay(self,money): # 继承Payment类,但是先找自己里面是否有pay函数,有就用自己的,没有才找父类 print('已经使用支付宝支付了%s元' % money) # 再定义一个Applepay类 class Aapplepay(Payment): # 继承Payment类,但是先找自己里面是否有pay函数,有就用自己的,没有才找父类,因为这里面没有pay函数, # 所以执行父类,所以最后将会报’NotImplementedError‘的错误 def fuqian(self,money): # 这里不是使用pay函数 print('已经使用苹果支付了%s元' % money) def pay(pay_obj,money): # 统一支付入口,不管使用哪种方式,主要就是支付就可以了 pay_obj.pay(money) wechat = Wechatpay() # 实例化 ali = Alipay() # 实例化 app = Aapplepay() # 实例化 # 使用了开头的规范后,就不需要在进行调用方法pay才可以报错了了,直接进行实例化就可以, # 这样方便写代码的人很快就可以找出错误所在 # pay(wechat,100) # 通过微信支付100 # pay(ali,200) # 通过支付宝支付200 # pay(app,300) # 这里调用pay函数,但是前面Applepay里面使用的不是pay函数而是fuqian,所以这里结果将会报错
运行结果:
Traceback (most recent call last): File "<encoding error>", line 32, in <module> TypeError: Can't instantiate abstract class Aapplepay with abstract methods pay
这样就可以引出用代码实现接口类的大致结构,类似的结构如下所示:
from abc import abstractmethod,ABCMeta class Payment(metaclass=ABCMeta): # 默认的元类type @abstractmethod def pay(self,money): # 规范子类必须含有pay方法 pass class A(Payment): def pay(self,money):pass class B(Payment): def pay(self,money):pass class C(Payment): def pay(self,money):pass
其实接口类和抽象类都是起到一个规范子类,约束子类的一个作用,不同的地方是:
接口类:支持多继承,接口类中的所有方法都必须不能实现,这样才能起到规范的作用---Java中
抽象类:不支持多继承,抽象类中的方法可以有一些代码的实现---Java中
原文地址:https://www.cnblogs.com/wxm422562/p/11006498.html
- JDK容器学习之LinkedHashMap (一):底层存储结构分析
- Linux基础(day60)
- 16.5/16.6/16.7 配置Tomcat虚拟主机
- JDK容器学习之LinkedHashMap(二):迭代遍历的实现方式
- React Native 实现基于react-native-tab-navigator库Tab切换封装
- 16.4 配置Tomcat监听80端口
- JDK容器学习之Queue:LinkedBlockingQueue
- Linux基础(day59)
- 16.3 安装Tomcat
- 16.2 安装jdk
- UITabBarController实现Tab切换
- React Native库版本升级与降级
- Java并发学习之Volatile及内存模型探究
- Java并发学习之CountDownLatch实现原理及使用姿势
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- mysqlbinlog命令详解 Part 1-实验环境准备
- mysqlbinlog命令详解 Part 2 -MySQL 事件类型
- mysqlbinlog命令详解 Part 4 -查看行事件具体SQL语句
- mysqlbinlog命令详解 Part 5 通过位置和时间查看日志
- mysqlbinlog命令详解 Part 6 读取远程MySQL服务器日志
- mysqlbinlog命令详解 Part 7 备份二进制日志文件
- mysqlbinlog命令详解 Part 8 指定 Server ID
- mysqlbinlog命令详解 Part 9 MySQL备份策略
- mysqlbinlog命令详解 Part 10 恢复MySQL
- mysqldump命令详解 Part 2- 建立触发器 事件
- mysqlbinlog命令详解 Part 11 其他的一些参数
- mysqldump命令详解 Part 1 -MySQL测试数据的构造
- mysqldump命令详解 Part 3- 备份全库
- mysqldump命令详解 Part 4-备份单表
- mysqldump命令详解 Part 5-按条件备份表数据