python之面向对象进阶

时间:2021-04-16 22:43:05

接口类

抽象类

钻石继承

多态

鸭子类型

接口类

接口类

继承有两种用途:

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

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

 代码如下

class Applepay:
    def pay(self,money):
        print('apple pay 支付了%s'%money)

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

class Wechatpay:
    def fuqian(self,money):
        print('微信支付了%s'%money)

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

apple1 = Applepay()#实例化一个对象
apple1.pay(20)#调用里面的函数
payment(apple1,50)#通过payment函数调用也可以
 

但是我们实例化一个Wechatpay不会报错但是如果调用pyament函数就会出错

class Applepay:
    def pay(self,money):
        print('apple pay 支付了%s'%money)

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

class Wechatpay:
    def fuqian(self,money):
        print('微信支付了%s'%money)

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

# apple1 = Applepay()#实例化一个对象
# apple1.pay(20)#调用里面的函数
# payment(apple1,50)#通过payment函数调用也可以

wechat1 = Wechatpay()
payment(wechat1,200)

这不是我们想要的结果,我们希望在函数运行时就会发现发现(实例化时就会发现错误)

通过调用接口类,下面所有的类都要根据接口类的格式来

from abc import ABCMeta,abstractmethod
class Payment(metaclass = ABCMeta):  #metaclass --> 元类
    @abstractmethod
    def pay(self,money):pass

class Applepay(Payment):
    def pay(self,money):
        print('apple pay 支付了%s'%money)

class Alipay(Payment):
    def pay(self,money):
        print('支付宝 支付了%s'%money)

class Wechatpay(Payment):
    def fuqian(self,money):
        print('微信支付了%s'%money)
wechat1 = Wechatpay()#实例化时就会报错

接口类的作用:约束继承接口类的子类必须实现被abstractmethod来装饰,在接口类中不要做实现,接口类不能被实例化。

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

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

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

接口类符合:依赖倒置原则

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

抽象类(在类中的方法可以实现一定的实现)(从小范围到大范围

from abc import ABCMeta,abstractmethod
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        print('打开粮食的袋子')#抽象类可以实例化一些方法
        print('放一个吃饭的碗')
        print('把粮食倒在碗里')

    @abstractmethod
    def sleep(self):
        pass

class Dog(Animal):
    def eat(self):
        super().eat()#重写父类方法
        print('dog is eating')#给子类一个新的方法

    def sleep(self):
        print('dog is sleeping')
d=Dog()
d.eat()

我们发现抽象类与接口类的区别就是在类内是否可以实现。

#抽象类
#在Python里 默认是有的
#父类的方法 子类必须实现
#抽象类 不能被实例化
#抽象类内的方法 可以被简单实现
#接口类(在抽象类的基础上)
#在python里 默认是没有的
#接口类中的方法 不能被实现
#原则:抽象类最好不要用多继承,而接口类可以

抽象类与接口类的区别:

当几个子类的父亲有相同的功能需要被实现的时候就用抽象类。

当几个子类有相同的功能,但是实现是各个不相同的时候就用接口类。

钻石继承      

python里分为新式类和经典类。新式类是广度优先;经典类是深度优先。在新式类内可以通过.mro来看到继承的顺序。

总结:

继承的作用:    

减少代码的重用
提高代码可读性
规范编程模式


几个名词:

抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。
继承:子类继承了父类的方法和属性
派生:子类在父类方法和属性的基础上产生了新的方法和属性

 

抽象类与接口类

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


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

钻石继承:

新式类:广度优先
经典类:深度优先

多态:

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

class Animal:pass
class Cat(Animal):
    def eat(self):
        print('cat eat')
class Dog(Animal):
    def eat(self):
        print('dog eat')
def eat_func(a):
    a.eat()

c = Cat()
eat_func(c)
d = Dog()
eat_func(d)



#python自带多态:#1 同一类事物的不同状态
#2 操作的时候不需要关心这个对象的数据类型,只要去用就可以了
鸭子类型

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

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

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