zoukankan      html  css  js  c++  java
  • DAY18 面向对象三大特性之继承

    继承

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

      在python3.x版本中,所有的类都默认继承object类。

    1.继承与重用

      首先,我们来看看一个例子:

    # 猫类:吃喝睡,爬树
    # 狗类:吃喝睡,看家
    
    #一。通过之前对面向对象的学习,我们可以轻易的定义出这两个类来:
    class Cat:
        def __init__(self,name,kind,food):
            self.name = name
            self.kind = kind
            self.food = food
    
        def eat(self):
            print('%s吃%s'%(self.name,self.food))
        def drink(self):
            print('%s喝水'%self.name)
        def sleep(self):
            print('%s在睡觉'%self.name)
        def climb(self):
            print('%s在爬树'%self.name)
    
    class Dog:
        def __init__(self,name,kind,food):
            self.name = name
            self.kind = kind
            self.food = food
    
        def eat(self):
            print('%s吃%s'%(self.name,self.food))
        def drink(self):
            print('%s喝水'%self.name)
        def sleep(self):
            print('%s在睡觉'%self.name)
        def look_after_home(self):
            print('%s在看家'%self.name)
    

      但是再往深入探讨,我们会发现其实编写的猫类和狗类代码中,很多都冗余代码。有什么方式能够把重复的代码提取出来吗?当然有,这时候就可以用到继承的思想,父类中的所有属性和方法都可以被子类使用。

    #二。把冗余的代码提出来,抽象出一个宠物类,让猫类和狗类都继承这个宠物类。
    class Pet:
        def __init__(self,name,kind,food):
            self.name = name
            self.kind = kind
            self.food = food
    
        def eat(self):
            print('%s吃%s'%(self.name,self.food))
        def drink(self):
            print('%s喝水'%self.name)
        def sleep(self):
            print('%s在睡觉'%self.name)
    
    class Cat(Pet):
        def climb(self):
            print('%s在爬树'%self.name)
    
    
    class Dog(Pet):
        def kanjia(self):
            print('%s在看家'%self.name)
    
    
    tom = Cat('Tom','暹罗猫','猫粮')   #子类使用名字(静态变量和方法),如果在子类中没有,就使用父类的
    hei = Dog('小黑','二哈','狗粮')
    
    tom.climb()
    hei.kanjia()
    

    2.继承与派生

      子类也可以定义自己特有的属性或者重新这些属性(但并不会影响到父类),一旦定义了自己的属性且与父类同名时,这种属性称为派生属性。子类的对象调用这个属性时,会直接选择子类中的。

    class Pet:
        def __init__(self,name,kind,food):
            print('IN PET')
            self.name = name
            self.kind = kind
            self.food = food
        def eat(self):
            print('%s吃%s'%(self.name,self.food))
        def drink(self):
            print('%s喝水'%self.name)
        def sleep(self):
            print('%s在睡觉'%self.name)
    
    class Cat(Pet):
        def __init__(self,name,kind,food,eye_color):
            print('IN CAT')
            self.eye_color = eye_color   #派生属性
            # Pet.__init__(name,kind,food)
            super().__init__(name,kind,food)  #super方法,可以省去self
        def climb(self):
            print('%s在爬树'%self.name)
    
    
    class Dog(Pet):
        def kanjia(self):
            print('%s在看家'%self.name)
    
    
    tom = Cat('阿猫','橘猫','猫粮','绿色')
    print(tom.eye_color)
    
    # 派生经典考题:
    class Foo:
        def __init__(self):
            self.func()
        def func(self):
            print('in tho foo')
    
    class Son(Foo):
        def func(self):
            print('in the son')
    
    s1 = Son()
    >>>
    in the son
    
    ################
    当self去调用某个方法的时候,不要看self在哪里,而是要明确self代表的到底是谁。

      派生总结:

      1.当子类中方法要被调用的时候,子类的对象会直接选择子类中的方法。

      2.父类的方法不会被自动执行。

      3.如果我们既要执行子类的方法又要执行父类中的方法,那么需要在子类的方法中调用父类的方法,有以下两种方法:

      (1)父类名.方法名(self,参数...)

      (2)super().方法名(参数...)   #关于super的查找顺序,请继续往下看。

    3.抽象类

      抽象类在python中使用的不是特别多,但是在以后的工作中,公司有可能会使用抽象类来制定开发的规则,在以后看源码的过程中,也可能会碰到抽象类的概念。试想一个场景:在今后的多人开发,功能复杂,许多后期拓展功能的项目中,代码的规范变得尤其的重要,而此时,抽象类就能够起到一个很好的模板作用。

      抽象类只是一个模板的规范,基本不会实现什么功能,所以抽象类是不可以被实例化的。

    #定义抽象类,需要引入一个模块。
    
    from abc import ABCMeta,abstractmethod
    class Payment(metaclass=ABCMeta):       #抽象类必须继承一个叫ABCMeta的类
        @abstractmethod                     #抽象类规定的方法,用abstractmethod装饰器装饰,规定了
        def pay(self):pass                   后面凡是继承该抽象类的子类都必须有一个同名的方法。
    
    class Alipay(Payment):
        def pay(self,money):
            print('使用支付宝支付了%s元'%money)
    

    4.多继承

      在python中允许一个子类是可以继承多个父类的。

    class ParentClass1:  #定义父类1
        pass
    
    class ParentClass2:  #定义父类2
        pass
    
    class ChildClass(ParentClass1):   #定义子类(继承父类1) 单继承
        pass
    
    class ChildClass2(ParentClass1,ParentClass2):  #多继承
        pass
    

      “__base__”:显示子类的一个父类。

      “__bases__”:显示子类的所有父类。

    5.新式类与经典类

      python3.x所有的类都是新式类,所有的新式类都有一个默认继承的父类,叫做object类。

      python2.7中经典类和新式类并存。

        class Student:Pass   #经典类

        class Student(object):pass  #新式类

      总结:

      (1)继承了object的类都是新式类。

      (2)在py3中所有的类都是新式类。

      (3)在py2中既有新式类也有经典类。

      一.多继承的顺序/新式类和经典类之间的区别?

     (1)钻石继承:广度优先。

      新式类的所有多继承关系寻找方法的顺序--->遵循广度优先。

      mro()--->显示多继承的继承顺序。

      super()--->super方法不是单纯的寻找父类,在多继承中,是遵循mro循序的。

    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()
    print(D.mro())              #新式类遵循广度优先。
    >>>
    A
    C
    B
    D
    [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    

      

     总结:

      新式类在多继承时,遵循广度优先。

      经典类在多继承时,遵循深度优先。

      

  • 相关阅读:
    DLL相关注意
    给我个理由要用虚析构函数
    字符指针常量和字符数组
    给自己普及网络基本知识
    面向对象三大基本特性,五大基本原则
    C/C++内存区域划分
    C++多态性
    Java XML Schema详解
    Java SE 第一百零五讲 对象的克隆与浅拷贝
    Java SE 第九十七~一百零五讲 线程与进程
  • 原文地址:https://www.cnblogs.com/hebbhao/p/9549579.html
Copyright © 2011-2022 走看看