zoukankan      html  css  js  c++  java
  • 面向对象:继承

    定义:新建的一个类继承另外一个类,另外一个类称为父类,也称为基类或超类。新建的类称为派生类或者子类
    作用:减少代码的重复性,提高可读性,规范编程方式
    继承分为新式类和经典类,又分为单继承和新继承
    经典类:python2当中默认为经典类,继承object后为新式类
    新式类:python3当中只有新式类,默认继承object,拥有方法mro,用于解析类的执行顺序
    单继承:直接找父类
    多继承:钻石继承最为经典,在经典类中,钻石继承为深度优先,而在新式类中,为广度优先。
      广度优先:新式类
      深度优先:经典类
    派生:子类在父类的方法和属性的基础上产生了新的属性和方法,称为派生属性和派生方法
    单继承:
    class A:
        pass
    
    class B(A):
        pass
    多继承:
    class A:
        pass
    
    class B:
        pass
    
    class C(A,B):
        pass
    例:
    # 下方的人狗大战,代码重复性太高,人是动物,狗是动物,他们有相同的属性,这时则可以创建一个动物类,让人和狗继承这个类,即动物为父类,人和狗为子类。
    
    class Person:
        def __init__(self,name,hp,aggr,sex):
            self.name = name
            self.hp = hp
            self.aggr = aggr
            self.sex = sex
        def kick(self,dog):
            dog.hp -= self.aggr
            return '%s踢了狗%s,狗剩余%s血'%(self.name,dog.name,dog.hp)
    
    
    class Dog:
        def __init__(self,name,hp,aggr,sex):
            self.name = name
            self.hp = hp
            self.aggr = aggr
            self.sex = sex
    
        def bite(self,person):
            person.hp -= self.aggr
            return '狗%s咬了%s,人剩余%s血'%(self.name,person.name,person.hp)
    
    aike = Person('aike',1000,100,'')
    chenfan = Dog('chenfan',500,50,'taddy')
    print(aike.kick(chenfan))
    print(chenfan.bite(aike))
    使用继承后:
    class Animal:  #父类,基类,超类
        def __init__(self,name,hp,aggr,sex):
            self.name = name
            self.hp = hp
            self.aggr = aggr
            self.sex = sex
    
    class Person(Animal):  #子类,派生类
        def kick(self,dog):
            dog.hp -= self.aggr
            return '%s踢了狗%s,狗剩余%s血'%(self.name,dog.name,dog.hp)
    
    class Dog(Animal):    #子类,派生类
        def bite(self,person):
            person.hp -= self.aggr
            return '狗%s咬了%s,人剩余%s血'%(self.name,person.name,person.hp)
    
    aike = Person('aike',1000,100,'')
    chenfan = Dog('chenfan',500,50,'taddy')
    print(aike.kick(chenfan))
    print(chenfan.bite(aike))

    单继承,派生属性、派生方法、super方法:
    class Animal:  #父类,基类,超类 ,python当中所有父类默认继承object类
        def __init__(self,name,hp,aggr,sex):
            self.name = name
            self.hp = hp
            self.aggr = aggr
            self.sex = sex
        def func1(self):
            print('测试super')
    
    class Person(Animal):  #子类,派生类
        def __init__(self,name,hp,aggr,sex,money): #人要有钱这个属性
            # Animal.__init__(self,name,hp,aggr,sex)
            # super().__init__(name,hp,aggr,sex)#super,等同于上一句的类调用,但是不用传self,因为在类的内部使用super方法,默认找父类,不用填写参数,等同于下面一句代码
            super(Person,self).__init__(name,hp,aggr,sex)#括号内为自己的类名
            self.money = money #钱属于派生属性
        def kick(self,dog): #派生方法
            dog.hp -= self.aggr
            return '%s踢了狗%s,狗剩余%s血'%(self.name,dog.name,dog.hp)
        def person_weapon(self,weapon): #获取武器
            if (self.money - weapon.price) > 0:
                self.money -= weapon.price
                self.weapon = weapon
                self.aggr += weapon.aggr
            else:
                return '赶紧充钱'
    
    class Dog(Animal):    #子类,派生类
        def bite(self,person): #派生方法
            person.hp -= self.aggr
            return '狗%s咬了%s,人剩余%s血'%(self.name,person.name,person.hp)
    
    class Weapon: #用钱可以买武器
        def __init__(self,name,price,aggr):
            self.name = name
            self.price = price
            self.aggr = aggr
        def func(self):
            pass
    
    aike = Person('aike',1000,100,'',1000)
    chenfan = Dog('chenfan',500,50,'taddy')
    stick = Weapon('stick',200,50)
    aike.person_weapon(stick)#装上武器+50攻击
    print(aike.kick(chenfan))
    print(chenfan.bite(aike))
    print(aike.money) #装上武器,钱减少
    super(Person,aike).func1()#在类外部使用需要传子类名和对象,调用方法时,只能调用父类的方法。
    结论:
    1、父类中没有的属性 在子类中出现 叫做派生属性
    2、父类中没有的方法 在子类中出现 叫做派生方法
    3、只要是子类的对象调用,子类中有的名字 一定用子类的,子类中没有才找父类的,如果父类也没有报错
    4、super方法:只在新式类中才有,作用是调用父类的方法,与父类名调用方法的作用相同,但是父类名调用需传self。
    在类中使用不用填参数,默认找父类,不用传self
    在类外部使用需要传子类名和对象,调用方法时,只能调用父类的方法。

    多继承:
    #钻石继承1
    class A:
        def func(self):
            print('这是A')
    class B(A):
        def func(self):
            print('这是B')
    class C(A):
        def func(self):
            print('这是C')
    class D(B,C):
        def func(self):
            print('这是D')
    
    d = D()
    d.func()
    python3当中只有新式类,调用顺序遵循广度优先: D-->B-->C-->A
    #钻石继承2
    class A:
        def func(self):
            print('这是A')
    class B(A):
        def func(self):
            print('这是B')
    class E:
        def func(self):
            print('这是E')
    class C(E):
        def func(self):
            print('这是C')
    class D(B,C):
        def func(self):
            print('这是D')
    
    d = D()
    d.func()
    print(D.mro())#[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>]
    python3当中只有新式类,调用顺序遵循广度优先: D-->B-->A-->C-->E


    #钻石排列3
    class A:
        def func(self):
            print('这是A')
    class B(A):
        def func(self):
            print('这是B')
    class C(A):
        def func(self):
            print('这是C')
    class E(B):
        def func(self):
            print('这是E')
    class F(C):
        def func(self):
            print('这是F')
    class D(E,F):
        def func(self):
            print('这是D')
    
    d = D()
    d.func()
    print(D.mro())#[<class '__main__.D'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.F'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    python3当中只有新式类,调用顺序遵循广度优先: D-->E-->B-->F-->C-->A

    经典类为深度优先:即一条路找到低,找不到则换一条路。

    关于super:

    class A:
        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')
    
    d = D()
    d.func()
    
    #打印为:
    这是A
    这是C
    这是B
    这是D

    super的本质:不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的,所以寻找顺序为D-->B-->C-->A

  • 相关阅读:
    check事件
    JAVA----泛型
    JAVA集合的遍历for循环、Iterator迭代器
    JAVA 集合的定义分类
    JAVA面向对象---方法的重写与重载
    JAVA 面向对象---继承
    JAVA 面向对象
    JAVA ArrayList集合
    JAVA基础测试
    JAVA中 引用数据类型(类)
  • 原文地址:https://www.cnblogs.com/aizhinong/p/11454731.html
Copyright © 2011-2022 走看看