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

一,接口类

继承有两种用途:

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

二:声明某个子类兼容于某基类,定义一个接口类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 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
30 p = Wechatpay()
31 pay(p,200)   #执行会报错

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

借用abc模块来实现接口

 1 from abc import ABCMeta,abstractmethod
 2
 3 class Payment(metaclass=ABCMeta):
 4     @abstractmethod
 5     def pay(self,money):
 6         pass
 7
 8
 9 class Wechatpay(Payment):
10     def fuqian(self,money):
11         print(‘微信支付了%s元‘%money)
12
13 p = Wechatpay() #不调就报错了

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

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

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

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

*****接口提取了一群类共同的函数,可以把接口当做一个函数的集合。 然后让子类去实现接口中的函数。 这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。 归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。

二,抽象类

什么是抽象类

    与java一样,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.多继承问题

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

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

2.方法的实现

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

三,钻石继承

 1 class A(object):
 2     def test(self):
 3         print(‘from A‘)
 4
 5 class B(A):
 6     def test(self):
 7         print(‘from B‘)
 8
 9 class C(A):
10     def test(self):
11         print(‘from C‘)
12
13 class D(B):
14     def test(self):
15         print(‘from D‘)
16
17 class E(C):
18     def test(self):
19         print(‘from E‘)
20
21 class F(D,E):
22     # def test(self):
23     #     print(‘from F‘)
24     pass
25 f1=F()
26 f1.test()
27 print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
28
29 #新式类继承顺序:F->D->B->E->C->A
30 #经典类继承顺序:F->D->B->A->E->C
31 #python3中统一都是新式类
32 #pyhon2中才分新式类与经典类
33
34 继承顺序

继承原理

python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如

>>> F.mro() #等同于F.__mro__
[<class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>]

为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

四,多态

多态指的是一类事物有多种形态

动物有多种形态:人,狗,猪

 1 import abc
 2 class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
 3     @abc.abstractmethod
 4     def talk(self):
 5         pass
 6
 7 class People(Animal): #动物的形态之一:人
 8     def talk(self):
 9         print(‘say hello‘)
10
11 class Dog(Animal): #动物的形态之二:狗
12     def talk(self):
13         print(‘say wangwang‘)
14
15 class Pig(Animal): #动物的形态之三:猪
16     def talk(self):
17         print(‘say aoao‘)

文件有多种形态:文本文件,可执行文件

 1 import abc
 2 class File(metaclass=abc.ABCMeta): #同一类事物:文件
 3     @abc.abstractmethod
 4     def click(self):
 5         pass
 6
 7 class Text(File): #文件的形态之一:文本文件
 8     def click(self):
 9         print(‘open file‘)
10
11 class ExeFile(File): #文件的形态之二:可执行文件
12     def click(self):
13         print(‘execute file‘)

多态性

一 什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)

多态性是指在不考虑实例类型的情况下使用实例

在面向对象方法中一般是这样表述多态性:
向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。
也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同

多态性分为静态多态性和动态多态性

  静态多态性:如任何类型都可以用运算符+进行运算

  动态多态性:如下

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

鸭子类型

逗比时刻:

  Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’

python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象

也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。

例1:利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法

例2:序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系

 1 #二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
 2 class TxtFile:
 3     def read(self):
 4         pass
 5
 6     def write(self):
 7         pass
 8
 9 class DiskFile:
10     def read(self):
11         pass
12     def write(self):
13         pass
14
15 例子

#二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
class TxtFile:
    def read(self):
        pass

    def write(self):
        pass

class DiskFile:
    def read(self):
        pass
    def write(self):
        pass

时间: 2024-08-07 07:55:50

python开发面向对象基础:接口类&抽象类&多态&多继承的相关文章

python 2018.7.25 接口类,抽象类

python 没有接口这个概念 接口类,抽象类: 制定一个规范. from abc import ABCMeta,abstractmethodclass Payment(metaclass=ABCMeta): # 抽象类(接口类): @abstractmethod def pay(self): pass # 制定了一个规范 class Alipay(Payment): def __init__(self,money): self.money = money def pay(self): prin

Python_015(面向对象(接口类,抽象类,多态,封装)

一.抽象类与接口类 1.抽象类:抽象即类似或者说比较像的部分,继承描述的是父类与子类的一种关系,要找出这种关系,必须先抽象再继承; a:抽象分成两个层次: 1)由对象->类:将两个有相似地方的对象抽取成类; 2)由类->父类:将两个有相似地方的类抽取成父类; :抽象最主要的作用就是划分类别(可以隔离关注点,降低复杂度) 2.为什么要有抽象类 与Java一样,Python也有抽象类的概念,需要借助模块实现,它是一个特殊的类,特殊之处在于只能被继承,不能被实例化; 类是从一些对象中抽取相同的内容而

python之面向对象(接口和抽象类)

一.接口 什么是接口 继承有两种用途: 1:继承基类的方法,并且做出自己的改变或者扩展(代码重用). 2:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能. class File: #定义接口File类来模仿接口的概念. def read(self): #定接口函数read pass def write(self): #定义接口函数write pass class Txt(File): #

python开发面向对象基础:组合&amp;继承

一,组合 组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合      人类装备了武器类就是组合 1.圆环,将圆类实例后传给圆环类 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 #circle,圆类 5 from math import pi 6 class Circle: 7 def __init__(self,radius): 8 self.radius = radius 9 def perimeter(self): 10

python开发面向对象基础:封装

一,封装 [封装] 隐藏对象的属性和实现细节,仅对外提供公共访问方式. [好处] 1. 将变化隔离: 2. 便于使用: 3. 提高复用性: 4. 提高安全性: [封装原则] 1. 将不需要对外提供的内容都隐藏起来: 2. 把属性都隐藏,提供公共方法对其访问. 私有变量和私有方法 在python中用双下划线开头的方式将属性隐藏起来(设置成私有的) 私有变量 #其实这仅仅这是一种变形操作 #类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式: class A: __N=0 #类的数

python开发面向对象基础:人狗大战学面向对象

一,通过函数写人狗大战这个故事 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 4 #1.函数 人模子 5 def person(name,level,life_value): 6 p_dic = { 7 'name':name, 8 'level':level, 9 'life_value':life_value 10 } 11 return p_dic 12 joker = person('joker',100,4000) 13 14 #函数

面向对象:接口类、抽象类

# python 没有接口这个概念# 接口类,抽象类: 制定一个规范. 接口类,抽象类:python中就是一样的 1,归一化设计. 2,制定一个规范,凡是继承我类的类,必须有我规定的方法. # 第一版 class Alipay: def __init__(self,money): self.money = money def pay(self): print('使用支付宝支付了%s' %self.money) class Jdpay: def __init__(self, money): sel

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

python 使用abc实现接口类/虚类 具体类 class BaseA: def run(self): print('base A running') class ChildA(BaseA): def run(self): print('child a') # 具体类可以直接继承也可以实现多态 a = BaseA() a.run() a = ChildA() a.run() 虚类 class BaseB(): @abc.abstractmethod def run(self): return

接口类抽象类

接口类(抽象类): 在python中是没有接口类,可以把接口类和抽象类视为同一种定义:制定一个规范举例:收到项目经理的要求,写一个支付: #第一版 class Alipay: def __init__(self,money): self.money = money def pay(self): print('zfb支付了%s' % self.money) class Jd: def __init__(self, money): self.money = money def pay(self):