欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

day 25-1 接口类、抽象类、多态

程序员文章站 2022-05-17 14:48:47
# 接口类:python 原生不支持# 抽象类:python 原生支持的 接口类 首先我们来看一个支付接口的简单例子 接口类的多继承 这是三种动物tiger 走路 游泳swan 走路 游泳 飞oldying 走路 飞 为了避免代码重复,我们写以下三个类下面就是实现了 接口类的规范 不需要有功能实现的 ......

# 接口类:python 原生不支持
# 抽象类:python 原生支持的

接口类

首先我们来看一个支付接口的简单例子

from abc import abstractmethod,abcmeta #我们也可以创建一个规范类
class payment(metaclass=abcmeta):  # 元类 默认的元类 type
    @abstractmethod
    def pay(self,money):
        raise notlmplemented

#规范类要求需要实现一个 叫做 pay 的方法
#这样在不调用的情况下 就会抛出错误  在实例化时就可以发现这个问题

# 规范 :接口类或者抽象类都可以
# 接口类 支持多继承,接口类中的所有的方法都必须不能实现 —— java
# 抽象类 不支持多继承,抽象类中方法可以有一些代码的实现 —— java

class payment:
    def pay(self,money):  #2.没有实现该方法,就会抛出这个异常,用来隐藏 1 处的错误
        raise notlmplemented  #原理就是 如果不实现 pay 方法 就会抛出这个报错
#报错如下
#nameerror: name 'notlmplemented' is not defined

class weipay(payment):
    def pay(self,money):
        print('微信支付了%s元'%money)

class alipay(payment):
    def pay(self,money):
        print('支付宝支付了%s元'%money)

class apppay(payment):
    def pays(self,money):  #1.如果这里的 pay 换成了其他名字就会报错  与下面的 pay 函数冲突了
        print('苹果支付了%s元'%money)
wei = weipay()
ali = alipay()
app = apppay()

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

pay(wei,100)
pay(ali,100)
pay(app,100)
#weipay.pay(100)
#alipay.pay(100)

 

接口类的多继承

这是三种动物
tiger      走路  游泳
swan     走路  游泳 飞
oldying  走路  飞

为了避免代码重复,我们写以下三个类
下面就是实现了 接口类的规范 不需要有功能实现的代码

#下面就是实现了 接口类的规范 不需要有功能实现的代码
from abc import abstractmethod,abcmeta
class swim_animal(metaclass=abcmeta):
    @abstractmethod
    def swim(self):pass

class walk_animal(metaclass=abcmeta):
    @abstractmethod
    def walk(self):pass

class fly_animal(metaclass=abcmeta):
    @abstractmethod
    def fly(self):pass

#继承了类里面的相应的方法就必须要写
class tiger(walk_animal,swim_animal):
    def walk(self):
        pass
    def swim(self):
        pass
class oldying(fly_animal,walk_animal):pass
class swan(swim_animal,walk_animal,fly_animal):pass

# 这样就完了 接口类  刚好满足接口隔离原则 面向对象开发的思想 规范

python 中没有接口类 这个只是类似,就是说 我要实现不同的功能,我就去继承不同的接口,来规范我当前类中要用那些函数

好了我们接下来稍稍完善下上满的例子

from abc import abstractmethod,abcmeta
class swim_animal(metaclass=abcmeta):
    @abstractmethod
    def swim(self):pass

class walk_animal(metaclass=abcmeta):
    @abstractmethod
    def walk(self):pass

class fly_animal(metaclass=abcmeta):
    @abstractmethod
    def fly(self):pass

class tiger(walk_animal,swim_animal):
    def walk(self,num):
        print('狮子跑了 %s 公里'%num)
    def swim(self,num):
        print('狮子游了 %s 公里'%num)

class oldying(fly_animal,walk_animal):
    def fly(self,num):
        print('老鹰飞了 %s 公里'%num)
    def walk(self,num):
        print('老鹰跑了 %s 公里'%num)


class swan(swim_animal,walk_animal,fly_animal):
    def fly(self,num):
        print('天鹅飞了 %s 公里'%num)
    def walk(self,num):
        print('天鹅跑了 %s 公里'%num)
    def swim(self,num):
        print('天鹅游了 %s 公里'%num)

t = tiger()
o = oldying()
s = swan()
#s.fly(5)

def action(action_obj,num):
    action_obj(num)

action(s.fly,5)

抽象类

如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性
在 python 中实现抽象类,抽象类一般是单继承
操作系统一切皆文件

我们来实现一个抽象类

import abc #利用 abc 模块实现抽象类

class all_file(metaclass=abc.abcmeta):
    all_type='file'
    @abc.abstractmethod #定义抽象方法,无需实现功能
    def read(self):
        '子类必须定义读功能'
        with open('filaname') as f:
            pass

    @abc.abstractmethod #定义抽象方法,无需实现功能
    def write(self):
        '子类必须定义写功能'
        pass

class txt(all_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print('文本数据的读取方法')
    def write(self):
        print('文本数据的读取方法')

class sata(all_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print('硬盘数据的读取方法')

    def write(self):
        print('硬盘数据的读取方法')

class process(all_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print('进程数据的读取方法')

    def write(self):
        print('进程数据的读取方法')

wenbenwenjian=txt()

yingpanwenjian=sata()

jinchengwenjian=process()

#这样大家都是被归一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()

print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)

抽象类 : 规范
一般情况下 单继承 能实现的功能都是一样的,所以在父类中可以有一些简单的基础实现
多继承的情况 由于功能比较复杂,所以不容易抽象出相同的功能的具体实现写在父类中

抽象类还是接口类 : 面向对象的开发规范 所有的接口类和抽象类都不能实例化

java:
java里的所有类的继承都是单继承,所以抽象类完美的解决了单继承需求中的规范问题
但对于多继承的需求,由于java本身语法的不支持,所以创建了接口interface这个概念
来解决多继承的规范问题

python:
python中没有接口类 :
python中自带多继承 所以我们直接用class来实现了接口类
python中支持抽象类 : 一般情况下 单继承 不能实例化(接口类抽象类)
且可以实现python代码

多态

python 天生支持多态,python 是动态强类型的语言

多态指的是一类事物有多种形态
动物有多种形态:人,狗,猪

import abc
class animal(metaclass=abc.abcmeta): #同一类事物:动物
    @abc.abstractmethod
    def talk(self):
        pass

class people(animal): #动物的形态之一:人
    def talk(self):
        print('say hello')

class dog(animal): #动物的形态之二:狗
    def talk(self):
        print('say wangwang')

class pig(animal): #动物的形态之三:猪
    def talk(self):
        print('say aoao')

people().talk()

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

多态性
什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)
多态性是指在不考虑实例类型的情况下使用实例

在面向对象方法中一般是这样表述多态性:
向不同的对象发送同一条消息( !!!obj.func():是调用了obj的方法func,又称为向 obj 发送了一条消息 func ),不同的对象在接收时会产生不同的行为(即方法)。

也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

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

鸭子类型

# 鸭子类型
# list tuple 如果说两个类型为鸭子类型 就是说这两个类型很相识
# 不崇尚根据继承所得来的相似
# 我只是自己实现我自己的代码就可以了。
# 如果两个类刚好相似,并不产生父类的子类的兄弟关系,而是鸭子类型
# list tuple 这种相似,是自己写代码的时候约束的,而不是通过父类约束的
# 优点:松耦合 每个相似的类之间都没有影响
# 缺点:太随意了,只能靠自觉

# 接口类和抽象类 在 python 当中的应用点并不是非常必要

封装

# 广义上面向对象的封装 :代码的保护,面向对象的思想本身就是一种
# 只让自己的对象能调用自己类中的方法

# 狭义上的封装 —— 面向对象的三大特性之一
# 属性 和 方法都藏起来 不让你看见

class person:
    __key = 123  # 私有静态属性
    def __init__(self,name,passwd):
        self.name = name
        #self.passwd = passwd  
        self.__passwd = passwd  #当属性前面加上 __ 就成为了私有属性

    def get_pwd(self):          #在类的内部使用方法调用 __passwd 属性
        print(self.__dict__)
        return self.__passwd    #只要在类的内部使用私有属性,就会自动的带上_类名

    def __login(self):          #私有方法
        self.__get.pwd()

per = person('ysg','123')
#print(alex.passwd)
#print(per.__passwd)  #然后就找不到该属性了
print(per.__dict__)   #这里还是可以看到  所有私有属性并不是约束数据安全的只是在代码级别加了一层密
print(per._person__passwd)  # _类名__属性名  这样调用就可以了 不过不应该去调取
print(per.get_pwd())

print(per.__login)   #调取不到
#定义类的私有属性 只能在类的内部 外部就不可以
per.__high = 1
print(per.__high)  #外部就可以直接使用

所有的私有 都是在变量的左边加上双下划线
  对象的私有属性
  类中的私有方法
  类中的静态私有属性
所有的私有的 都不能在类的外部使用