面向对象的三大特性————继承,多态

Posted 一种清孤不等闲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象的三大特性————继承,多态相关的知识,希望对你有一定的参考价值。

1,继承:继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称派生类或子类。

  一个类可以被多个类继承,一个类可以继承多个父类。

  没有继承父类默认继承object-----新式类,python3中都是新式类,object是所有python类的父类。

1.1单继承

class A():pass    #父类
class B():pass     #父类
class Ab(A):pass  #单继承
class C(A,B):pass     #多继承

查看继承

class A():pass
class Av(object):pass
class B():pass
class Ab(A,B):pass
print(Ab.__bases__)
print(A.__bases__)
print(Av.__bases__)
#(<class ‘__main__.A‘>, <class ‘__main__.B‘>)
#(<class ‘object‘>,)
#(<class ‘object‘>,)

抽象与继承,抽象即抽取类似或者说比较像的部分。

      继承:是基于抽象的结果,通过编程语言去实现它,先抽象,再用继承的方式去表达出抽象的结构。

技术分享图片
class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp

    def eat(self):
        print(吃药回血)
        self.hp+=100

class Dog(Animal):
    def __init__(self,name,aggr,hp,kind):
        Animal.__init__(self,name,aggr,hp)  #
        self.kind = kind       # 派生属性
    def eat(self):
        # Animal.eat(self)
        super().eat()
        #  如果既想实现新的功能也想使用父类原本的功能,还需要在子类中再调用父类
        self.teeth = 2
    def bite(self,person):   # 派生方法
        person.hp -= self.aggr

jin = Dog(金老板,100,500,吉娃娃)
jin.eat()
print(jin.hp)

class Person(Animal):
    def __init__(self,name,aggr,hp,sex):
        Animal.__init__(self,name,aggr,hp)
        self.sex = sex       # 派生属性
        self.money = 0       # 派生属性

    def attack(self,dog):
        dog.hp -= self.aggr

    def get_weapon(self,weapon):
        if self.money >= weapon.price:
            self.money -= weapon.price
            self.weapon = weapon
            self.aggr += weapon.aggr
        else:
            print("余额不足,请先充值")
alex = Person(alex,1,2,None)
alex.eat()
print(alex.hp)

jin.bite(alex)
print(alex.hp)
View Code

在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要父类中重命名的那个函数功能,应该使用调用普通函数的方式,即:类名.func(),在python3中,子类执行父类的方法可以直接用supre.func()方法。

技术分享图片
class A:
    def hahaha(self):
        print(A)

class B(A):
    def hahaha(self):
        super().hahaha()
        #super(B,self).hahaha()
        #A.hahaha(self)
        print(B)

a = A()
b = B()
b.hahaha()
super(B,b).hahaha()
View Code

父类中没有的属性,在子类中出现叫做派生属性;父类中没有的方法在子类中出现叫派生方法。

只要是子类的对象调用,子类中有的名字一定用子类,子类没有的才找父类。如果子类父类都有的,用子类的,用父类的,需要调用父类的:父类名.方法名,需要自己传self,super().方法名,不需要传self。

2,多继承

mro方法,查看继承顺序

新式类中的继承顺序:广度优先

技术分享图片
# class A(object):
#     def func(self): print(‘A‘)
#
# class B(A):
#     def func(self):
#        super().func()
#        print(‘B‘)
#
# class C(A):
#     def func(self):
#         super().func()
#         print(‘C‘)
#
# class D(B,C):
#     def func(self):
#        super().func()
#         print(‘D‘)
#
# b = D()
# b.func()
# print(B.mro())
#A,C,B,D
View Code

经典类中深度优先(没有mro方法)

super的本质:不只是单纯的找父类而是根据调用者的节点位置的广度优先顺序来的。

3,接口类与抽象类

3.1接口类:python原生不支持的

规范格式:模块abc模块

技术分享图片
# from abc import abstractclassmethod,ABCMeta
# class Animal(metaclass=ABCMeta):
#     @abstractclassmethod
#     def pay(self,money):
#         pass
# class Wecchat(Animal):
#     def pay(self,money):
#         print("已用微信支付了%s元"%money)
#
# class Alipay(Animal):
#     def pay(self,money):
#         print("已用支付宝支付了%s元"%money)

# class Applepay(Animal):
#     def pay(self,money):
#         print("已用App支付了%s元"%money)
# def pay(pay_obj,moeny):
#     pay_obj(moeny)
#
#
# wechat=Wecchat()
# ali=Alipay()
# app=Applepay()
# wechat.pay(23)
# ali.pay(54)
# app.pay(23)
View Code

3.2抽象类

类是从一堆对象中抽取相同的内容而来,那么抽象类就是从一堆类中抽取相同的内容而来的。

抽象类:规范

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

技术分享图片
#一切皆文件
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)
View Code

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

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

接口类与抽象类的总结:

pyhton中没有接口类,有抽象类,abc模块中metaclass=ABCMeta,@abstructmethod

本质是用来做代码规范的,希望在子类中实现和父类方法名字完全一样的方法。

抽象类与接口类的区别:

在java的角度上看是有区别的,java本来就支持单继承,所以有了抽象类;但java没有多继承,所以为了接口隔离原则,设计了接口这个概念,支持了多继承。

python中既支持单继承也支持多继承,所以对于接口类和抽象类的区别就不太明显,甚至在python中没有内置接口类。

二,多态

Python天生支持多态,多态指的是一类事物有多种形态

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

鸭子类型:不依赖父类的情况下实现两个相似的类中的同名方法。

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

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

# class List():
#     def __len__(self):pass
# class Tuple():
#     def __len__(self):pass
#
# def len(obj):
#     return obj.__len__()
#
# l = Tuple()
# len(l)
#
# # 强类型语言     多态
# # python 语言    鸭子类型

 

以上是关于面向对象的三大特性————继承,多态的主要内容,如果未能解决你的问题,请参考以下文章

面向对象之:三大特性:继承(已讲),封装,多态

19.Python面向对象之:三大特性:继承,封装,多态。

三大特性:封装,继承,多态

Python 入门 之 面向对象的三大特性(封装 / 继承 / 多态)

Python 面向对象的三大特性:封装,继承,多态

继承 多态 封装 Python面向对象的三大特性