抽象类与接口类

接口类

继承有两种用途:

  一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)

  二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

  1. class Alipay:
  2. '''
  3. 支付宝支付
  4. '''
  5. def pay(self,money):
  6. print('支付宝支付了%s元'%money)
  7.  
  8. class Applepay:
  9. '''
  10. apple pay支付
  11. '''
  12. def pay(self,money):
  13. print('apple pay支付了%s元'%money)
  14.  
  15. def pay(payment,money):
  16. '''
  17. 支付函数,总体负责支付
  18. 对应支付的对象和要支付的金额
  19. '''
  20. payment.pay(money)
  21.  
  22. p = Alipay()
  23. pay(p,200)

简单的支付功能

开发中容易出现的问题

  1. class Alipay:
  2. '''
  3. 支付宝支付
  4. '''
  5. def pay(self,money):
  6. print('支付宝支付了%s元'%money)
  7.  
  8. class Applepay:
  9. '''
  10. apple pay支付
  11. '''
  12. def pay(self,money):
  13. print('apple pay支付了%s元'%money)
  14.  
  15. class Wechatpay:
  16. def fuqian(self,money):
  17. '''
  18. 实现了pay的功能,但是名字不一样
  19. '''
  20. print('微信支付了%s元'%money)
  21.  
  22. def pay(payment,money):
  23. '''
  24. 支付函数,总体负责支付
  25. 对应支付的对象和要支付的金额
  26. '''
  27. payment.pay(money)
  28.  
  29. p = Wechatpay()
  30. pay(p,200) #执行会报错

接口初成:手动报异常:NotImplementedError来解决开发中遇到的问题

  1. class Payment:
  2. def pay(self):
  3. raise NotImplementedError
  4.  
  5. class Wechatpay(Payment):
  6. def fuqian(self,money):
  7. print('微信支付了%s元'%money)
  8.  
  9. p = Wechatpay() #这里不报错
  10. pay(p,200) #这里报错了

借用abc模块来实现接口

  1. from abc import abstractmethod,ABCMeta
  2. class Payment(metaclass=ABCMeta): # 元类 默认的元类 type
  3. @abstractmethod
  4. def pay(self,money):pass # 没有实现这个方法
  5. # 规范 :接口类或者抽象类都可以
  6. # 接口类 支持多继承,接口类中的所有的方法都必须不能实现 —— java
  7. # 抽象类 不支持多继承,抽象类中方法可以有一些代码的实现 —— java
  8. class Wechat(Payment):
  9. def pay(self,money):
  10. print('已经用微信支付了%s元'%money)
  11.  
  12. class Alipay(Payment):
  13. def pay(self,money):
  14. print('已经用支付宝支付了%s元' % money)
  15.  
  16. class Applepay(Payment):
  17. def pay(self,money):
  18. print('已经用applepay支付了%s元' % money)
  19.  
  20. def pay(pay_obj,money): # 统一支付入口
  21. pay_obj.pay(money)
  22.  
  23. # wechat = Wechat()
  24. # ali = Alipay()
  25. app = Applepay()
  26. # wechat.pay(100)
  27. # ali.pay(200)
  28. p = Payment()

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

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

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

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

在python中根本就没有一个叫做interface(Java中的)的关键字,上面的代码只是看起来像接口,其实并没有起到接口的作用,子类完全可以不用去实现接口 ,如果非要去模仿接口的概念,可以借助第三方模块:

http://pypi.python.org/pypi/zope.interface

twisted的twisted\internet\interface.py里使用zope.interface

文档https://zopeinterface.readthedocs.io/en/latest/

设计模式:https://github.com/faif/python-patterns

  1. 接口提取了一群类共同的函数,可以把接口当做一个函数的集合。
  2.  
  3. 然后让子类去实现接口中的函数。
  4.  
  5. 这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。
  6.  
  7. 归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
  8.  
  9. 比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。
  10.  
  11. 再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样
  12.  
  13. 为何要用接口

为何要用接口

抽象类

什么是抽象类

与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

为什么要有抽象类

如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

  比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。

从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。

  从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案

在python中实现抽象类

  1. #一切皆文件
  2. import abc #利用abc模块实现抽象类
  3.  
  4. class All_file(metaclass=abc.ABCMeta):
  5. all_type='file'
  6. @abc.abstractmethod #定义抽象方法,无需实现功能
  7. def read(self):
  8. '子类必须定义读功能'
  9. pass
  10.  
  11. @abc.abstractmethod #定义抽象方法,无需实现功能
  12. def write(self):
  13. '子类必须定义写功能'
  14. pass
  15.  
  16. # class Txt(All_file):
  17. # pass
  18. #
  19. # t1=Txt() #报错,子类没有定义抽象方法
  20.  
  21. class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
  22. def read(self):
  23. print('文本数据的读取方法')
  24.  
  25. def write(self):
  26. print('文本数据的读取方法')
  27.  
  28. class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
  29. def read(self):
  30. print('硬盘数据的读取方法')
  31.  
  32. def write(self):
  33. print('硬盘数据的读取方法')
  34.  
  35. class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
  36. def read(self):
  37. print('进程数据的读取方法')
  38.  
  39. def write(self):
  40. print('进程数据的读取方法')
  41.  
  42. wenbenwenjian=Txt()
  43.  
  44. yingpanwenjian=Sata()
  45.  
  46. jinchengwenjian=Process()
  47.  
  48. #这样大家都是被归一化了,也就是一切皆文件的思想
  49. wenbenwenjian.read()
  50. yingpanwenjian.write()
  51. jinchengwenjian.read()
  52.  
  53. print(wenbenwenjian.all_type)
  54. print(yingpanwenjian.all_type)
  55. print(jinchengwenjian.all_type)

抽象类与接口类

抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计

在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。

1.多继承问题

在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口

  1. # tiger 走路 游泳
  2. # swan 走路 游泳 飞
  3. # oldying 走路 飞
  4. from abc import abstractmethod,ABCMeta
  5. class Swim_Animal(metaclass=ABCMeta):
  6. @abstractmethod
  7. def swim(self):pass
  8.  
  9. class Walk_Animal(metaclass=ABCMeta):
  10. @abstractmethod
  11. def walk(self):pass
  12.  
  13. class Fly_Animal(metaclass=ABCMeta):
  14. @abstractmethod
  15. def fly(self):pass
  16.  
  17. class Tiger(Walk_Animal,Swim_Animal):
  18. def walk(self):
  19. pass
  20. def swim(self):
  21. pass
  22. class OldYing(Fly_Animal,Walk_Animal):pass
  23. class Swan(Swim_Animal,Walk_Animal,Fly_Animal):pass

接口的多继承

  1. 接口隔离原则:
  2. 使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。

2.方法的实现

在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现

python之路----继承的抽象类和接口类的更多相关文章

  1. Python面向对象 | 抽象类和接口类

    一.抽象类(规范的编程模式) 什么是抽象类 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化.抽象类的本质还是类,指的是一组类的相似性,而接口只强调函数属性的相似性. 为什么要有抽象类 ...

  2. php 抽象类和接口类

    PHP中抽象类和接口类都是特殊类,通常配合面向对象的多态性一起使用. 相同: ①两者都是抽象类,都不能实例化. ②只有接口类的实现类和抽象类的子类实现了 已经声明的 抽象方法才能被实例化. 不同: ① ...

  3. Python抽象类和接口类

    一.抽象类和接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名) ...

  4. python基础 抽象类(接口类)

    Python中没有接口.接口类,抽象类:定义 制定一个规范 #必须要导入from abc import ABCMeta,abstractmethod class Payment(metaclass = ...

  5. python's twenty-first day for me 抽象类和接口类以及多态

    归一化设计: 不管是哪一个类的对象,都调用同一个函数去完成相似的功能. class Alipay: def pay(self,money): print('使用支付宝支付了%s' % money) c ...

  6. 第二十八节:Java基础-进阶继承,抽象类,接口

    前言 Java基础-进阶继承,抽象类,接口 进阶继承 class Stu { int age = 1; } class Stuo extends Stu { int agee = 2; } class ...

  7. Java入门系列之类继承、抽象类、接口(五)

    前言 C#和Java关于类.抽象类.接口使用方式基本相似,只是对应关键字使用不同罢了,本节呢,我们只是对照C#和Java中关于这三个概念在具体使用时,看看有哪些不一样的地方. 类继承 C#和Java在 ...

  8. Java 对象的继承,抽象类,接口

    子父级继承 关键字 extends 首先创建一个父类 class Fu { String name; int a=1; public void word() { System.out.println( ...

  9. 抽象类,接口类,封装,property,classmetod,statimethod

    抽象类,接口类,封装,property,classmetod,statimethod(类方法,静态方法) 一丶抽象类和接口类 接口类(不崇尚用) 接口类:是规范子类的一个模板,只要接口类中定义的,就应 ...

随机推荐

  1. Spark2 Dataset之视图与SQL

    // 创建视图 data.createOrReplaceTempView("Affairs") val df1 = spark.sql("SELECT * FROM Af ...

  2. 【vue】---项目接口管理---【巷子】

    一.前言 在vue开发中,会涉及到很多接口的处理,当项目足够大时,就需要定义规范统一的接口 假设后端的文档分成了以下几个模块 1.发现模块 2.个人信息模块 3.商品模块 4.评论模块 ...... ...

  3. easyui-datagrid个人实例

    这个实例数据表格的功能,可以实现分页,增删改查功能 1.user.jsp <%@ page language="java" contentType="text/ht ...

  4. 启用yarn日志聚集功能

    在yarn-site.xml配置文件中添加如下内容: ##开启日志聚集功能        <property>                <name>yarn.log-ag ...

  5. flume学习笔记

    #################################################################################################### ...

  6. html中label及加上属性for之后的用法

    定义和用法 <label> 标签为 input 元素定义标签(label). label 元素不会向用户呈现任何特殊的样式.不过,它为鼠标用户改善了可用性,因为如果用户点击 label 元 ...

  7. -bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory

    本人使用mac系统,命令行工具使用的iterm2,登录自己的云主机的时候 每次都要提示如下错误 -bash: warning: setlocale: LC_CTYPE: cannot change l ...

  8. 009-jdk1.8版本新特性一-展方法,Lambda表达式,函数式接口、方法引用构造引用

    一.JDK1.8 名称:Spider(蜘蛛) 发布日期:2014-03-18 新特性: 1.1.扩展方法[接口的默认方法] Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 defaul ...

  9. java-小技巧-001-Long序列化到前端js不支持

    1.引入:jackson-mapper-asl-1.9.2.jar 2.导入: import org.codehaus.jackson.map.annotate.JsonSerialize;impor ...

  10. java-信息安全(十一)-非对称加密算法ECC以及ECDSA签名

    概述 信息安全基本概念: ECC算法(Elliptic curve cryptography,椭圆曲线密码学) 一.ECC加密解密[暂时无意义] 椭圆加密算法(ECC)是一种公钥加密体制,最初由Kob ...