、抽象类规范的编程模式

什么是抽象类

  抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。抽象类的本质还是类,指的是一组类的相似性,而接口只强调函数属性的相似性。

为什么要有抽象类

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

 

  • 抽象类是介于类和接口之间的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计。在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念

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

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

抽象类就是制定一个规则,让其他人按照我的规则写程序。 约定俗称规范,但是有人不按照这个执行。

归一化设计 强制指定规范.

写一个抽象类:

  • from abc import ABCMeta,abstractmethod
  • 需要用到abc模块,在这个类创建的时候指定 metaclass = ABCMeta
  • 在你希望子类实现的方法上加上 @abstramethod 装饰器

举例,支付宝和qq支付,统一支付方式:实例化的时候,有不规范的,直接报错呢

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 Wechatpay(Payment):
    def pay(self,money):
        print('使用微信支付了%s元' % money)

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

def pay(object,money):      # 归一化设计
    object.pay(money)       # 执行实例化对象的类方法

# p = Payment()  #抽象类不能实例化,TypeError: Can't instantiate abstract class Payment with abstract methods pay
a = Alipay()
a.pay(100)
pay(a,100)            # 上下效果相同

# Payment不需要pay的代码,只需要子类实现即可
# Payment没有任何代码实现,必须要求子类有同名的方法名

'''
执行输出:
使用支付宝支付了100元
使用支付宝支付了100元
'''

这个统一的方法,叫做归一化设计

  归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能

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

抽象类和接口类做的事情 :建立规范

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

  • 抽象类中所有被abstractmethod装饰的方法都必须被继承的子类实现。如果不实现,那么在实例化阶段将会报错

  • 无论是抽象类还是接口类metaclass=ABCMeta 都不可以被实例化。p = Payment() 报错

  • 如果抽象类没有abstractmethod装饰器,那么这个方法,子类不需要实现。把fuqian改成pay就可以实例化了

、接口类

接口类:定义一个接口对继承类进行约束,接口里有什么方法,继承类就必须有什么方法,接口中不能有任何功能代码

比如动物园里面的动物,会游泳,走路,爬树,飞行的动物。定义几个动物:

class Tiger(object):                # 老虎
    def walk(self):pass             # 走路
    def swim(self):pass             # 游泳

class Monkey(object):               # 猴子
    def walk(self):pass
    def climb(self):pass            # 爬树

class Swan(object):                  # 天鹅
    def walk(self): pass
    def swim(self): pass
    def fly(self):pass              # 飞行
    def cal_flying_speed(self):pass      # 计算飞行速度
    def cal_flying_height(self):pass      # 计算飞行高度

观察上面的代码,技能重复了。这样写,容易丢失方法。加一个鹦鹉,但是它少了一些飞行类的方法

class Parrot(object):
    def fly(self):pass
    def cal_flying_speed(self): pass 

怎么解决这个问题呢?定义一个抽象类A

from abc import ABCMeta, abstractmethod

class A(metaclass=ABCMeta):
    @abstractmethod
    def fly(self): pass

    @abstractmethod
    def cal_flying_speed(self): pass

    @abstractmethod
    def cal_flying_height(self): pass

class Tiger(object):            # 老虎
    def walk(self): pass        # 走路
    def swim(self): pass        # 游泳

class Monkey(object):           # 猴子
    def walk(self): pass

class Swan(A):                  # 天鹅
    def walk(self): pass
    def swim(self): pass
    def fly(self): pass         # 飞行
    def cal_flying_speed(self): pass  # 计算飞行速度
    def cal_flying_height(self): pass  # 计算飞行高度

class Parrot(A):
    def fly(self): pass
    def cal_flying_speed(self): pass

Swan()              # 没问题
Parrot()            # 报错

'''
执行报错:
TypeError: Can't instantiate abstract class Parrot with abstract methods cal_flying_height
'''

鹦鹉实例化时,报错,找不到方法cal_flying_height。这样就约束了飞行动物的方法。所有会走的动物,具有一些会走的动物特性。对于爬行动物,不能继承A,所以需要再定义一抽象类

from abc import ABCMeta,abstractmethod

class FlyAnimal(metaclass=ABCMeta):  # 飞行
    @abstractmethod
    def fly(self):pass        # 接口中的方法函数不能有任何内容

    @abstractmethod
    def cal_flying_speed(self):pass

    @abstractmethod
    def cal_flying_height(self):pass

class WalkAnimal(metaclass=ABCMeta):  # 走路
    @abstractmethod
    def walk(self):pass

class SwimAnimal(metaclass=ABCMeta):  # 游泳
    @abstractmethod
    def swim(self):pass

class Tiger(WalkAnimal,SwimAnimal):  # 老虎,继承走路和游泳
    def walk(self):pass  # 走路
    def swim(self):pass  # 游泳

class Monkey(WalkAnimal):  # 猴子
    def walk(self):pass
    def climb(self):pass  # 爬树

class Swan(FlyAnimal,WalkAnimal,SwimAnimal):  # 天鹅,继承飞行,走路,游泳
    def walk(self): pass
    def swim(self): pass
    def fly(self):pass  # 飞行    #调用时,要完成代码
    def cal_flying_speed(self):pass  # 计算飞行速度
    def cal_flying_height(self):pass  # 计算飞行高度

class Parrot(FlyAnimal):  # 鹦鹉,继承飞行
    def fly(self):pass
    def cal_flying_speed(self): pass
    def cal_flying_height(self): pass

#实例化
Tiger()
Monkey()
Swan()
Parrot() 

执行输出,就没有报错了。

接口隔离原则:

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

  • 不能使用单一的总接口来完成,所以需要定义多个抽象类,同时,不需要的接口不要给底层类继承。

抽象类和接口类总结:

  • 在python中,并没有什么不同,都是用来约束子类中的方法的;

  • 只要是抽象类和接口类中被abstractmethod装饰的方法,都需要被子类实现;

  • 当多个类有相同的功能也有不同的功能的时候,应该采用多个接口类来进行分别的约束

面试的时候,可能会问:什么是抽象类?什么是接口类?

抽象类 是python中定义类的一种规范,用来约束子类中的方法的。被abstractmethod装饰的方法,子类必须实现,否则实例化时报错。

接口类 满足接口隔离原则,且完成多继承的约束。如果不按照规范,在调用方法时,报错。

Python面向对象 | 抽象类和接口类的更多相关文章

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

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

  2. python开发面向对象基础:接口类&抽象类&多态&钻石继承

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

  3. python之路----继承的抽象类和接口类

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

  4. Python抽象类和接口类

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

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

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

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

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

  7. php 抽象类和接口类

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

  8. python 使用abc实现接口类/虚类(2.2)

    python 使用abc实现接口类/虚类 具体类 class BaseA: def run(self): print('base A running') class ChildA(BaseA): de ...

  9. python面向对象 : 抽象类(接口类),多态,封装(私有制封装)

    一. 抽象类(接口类) 与java一样, python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类, 它的特殊之处在于只能被继承, 不能被实例化. 从设计角度去看, 如果类是从现实对 ...

随机推荐

  1. Qt对话框之二:模态、非模态、半模态对话框

    一.模态对话框 模态对话框:阻塞同一应用程序中其它可视窗口输入的对话框.模态对话框有自己的事件循环,用户必须完成这个对话框中的交互操作,并且关闭了它之后才能访问应用程序中的其它任何窗口. 显示模态对话 ...

  2. Loj #3085. 「GXOI / GZOI2019」特技飞行

    Loj #3085. 「GXOI / GZOI2019」特技飞行 题目描述 公元 \(9012\) 年,Z 市的航空基地计划举行一场特技飞行表演.表演的场地可以看作一个二维平面直角坐标系,其中横坐标代 ...

  3. PHP curl cookie不识别

    PHP curl cookie不识别 所以curl的时候别用setcookie 用了也没用

  4. [转帖]mDNS原理的简单理解

    mDNS原理的简单理解 https://binkery.com/archives/318.html 发现还有avahi-daemon mdns 设置ip地址 等等事项 网络部分 自己学习的还是不够多 ...

  5. 运维开发实践——基于Sentry搭建错误日志监控系统

    错误日志监控也可称为业务逻辑监控, 旨在对业务系统运行过程中产生的错误日志进行收集归纳和监控告警.似乎有那么点曾相识?没错... 就是提到的“APM应用性能监控”.但它又与APM不同,APM系统主要注 ...

  6. k8s网络原理

    https://blog.csdn.net/watermelonbig/article/details/80646988 k8s中,每个 Pod 都有一个独立的 IP 地址,所有 Pod 在一个网络空 ...

  7. docker-machine命令安装

    $ base=https://github.com/docker/machine/releases/download/v0.16.0 && curl -L $base/docker-m ...

  8. SUCTF 2018——Anonymous(php匿名函数 \x00lambda_)

    题目地址:http://45.76.173.177:23334/ <?php $MY = create_function("","die(`cat flag.php ...

  9. 实验吧——看起来有点难(sql盲注)

    题目地址:http://ctf5.shiyanbar.com/basic/inject/ 首先当然是拿admin/admin来试试啊,多次测试发现,有两种错误提示 1.数据库连接失败! 2.登录失败, ...

  10. CDA数据分析【数据处理工具SPSS】

    一.概述 SPSS[Statistical Package for the Social Science]社会科学统计软件包.SPSS统计软件在社会学.经济学.心理学.教育学等多个学科的研究工作和通信 ...