python面向对象-继承&多态

**

一、继承特性

**
1、什么是继承
继承就是让类和类之间产生父子关系,子类可以拥有父类的静态属性和方法。
[继承就是可以获取另外一个类中的静态属性和普通方法。(并非所有成员)]
在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。(python中的继承分为:单继承和多继承)
2、继承中的子类和父类的概念
父类:用于被继承的类,称之为父类,也叫做基类,或者超类。
子类:继承其他类的类,称之为子类,也叫做派生类。
3、继承的作用
就是提高代码的重用率
**例1、**定义一个父类Animal,将Cat和Dog类中的相同功能抽取到Animal中

#父类
class Animal(object):
    type = '动物'
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def eat(self):
        print('吃...')
    def sleep(self):
        print('睡觉')
#子类
class Dog(Animal):
    def look_house(self):
        print('看大门...')
#子类
class Cat(Animal):
    def climb_tree(self):
        print('爬树...')


dog = Dog('哈士奇', 8)
dog.eat()#调用父类的方法
dog.sleep()
dog.look_house()
print(dog.type)
cat = Cat('橘猫', 10)
cat.eat()
cat.sleep()#调用父类的方法
cat.climb_tree()

查看继承的父类
格式:类名__bases__

print(Cat.__bases__)
print(Dog.__bases__)
print(Animal.__bases__)

注意:
(1)python3中如果一个类没有继承任何类,默认继承object类。我们管这种类叫做新式类。
(2)object类,可以说是python中的祖宗,所有的类都是从object类中继承下来的。
4、方法的复写
子类中定义了和父类中相同的方法,我们叫做方法的复写(派生方法)。实例对象调用此方法的时候就会调用自己类中的方法了。
什么时候使用方法的复写:当父类的方法不能满足子类的需求的时候,就可以使用方法的复写。
例1、

class Animal(object):
    type = '动物'
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print('吃。。。')

    def sleep(self):
        print('睡。。。')

class Dog(Animal):
   def look_house(self):
        print('看大门...')

    def eat(self):
        print('吃狗粮...')

    def sleep(self):
        print('睡觉轻...')
dog = Dog('二哈', 8)
dog.eat()
dog.sleep()

5、super()
当子类和父类有相同的方法的时候,子类默认会调用自己的方法,而不能使用父类的方法。如果想使用父类的方法,我们就可以使用super()方法来调用父类的方法
1.super(类名,对象名).方法()既可以在类的内部也可以在类的外部使用。
2.父类类名.方法名(self)–>Animal.eat(self) 既可以在内部也可也在外部使用
3.super().eat()–> 只能在类的内部。

class Animal(object):
    type = '动物'
    def eat(self):
        print('吃...')
    def sleep(self):
        print('睡觉')

class Dog(Animal):
    def look_house(self):
        print('看大门...')
    def eat(self):
        # super().eat() # 调用的是父类的eat()方法。
        # Animal.eat(self)  # 父类类名.方法名(self)
        print('吃狗粮...')

dog = Dog()
super(Dog, dog).eat()  # super(类名,对象名).方法()

6、init()方法

1.如果子类不复写__init__()方法,会自动调用父类的__init__()方法。
2.如果子类复写了__init__()方法,不会自动调用父类的__init__()方法。
(不推荐使用这种方式)
3. 推荐显示的调用父类的方法。super().init()

class Person(object):
    def __init__(self):
        print('person...')

class Student(Person):
    def __init__(self):
        super().__init__()
        print('student...')

student = Student()

注意:
存在隐患,例如父类的初始化方法有参数,子类初始化无参数,子类再调用父类的参数的时候就会报错。
7、派生属性
派生属性: 子类中添加的新属性
属性的覆盖:子类和父类有相同的属性的时候,将调用自己类中的属性

class Person(object):
    num = 10
    def __init__(self, name):
        print('person...')

class Student(Person):
    num = 20
    def __init__(self, name, age):  # age是派生属性
        super().__init__(name)
        self.name = name
        self.age = age
        print('student...')

    def eat(self):
        print(super().num)#通过super()调用父类的方法
        print('xxx')
        
student = Student('zs', 10)
print(student.age)
student.eat()
print(Student.num)#调用自己类中的属性

8、私有属性私有方法在继承中的表现

class Person(object):
    num = 10
    __num1 = 20
    def __test1(self):
        print('__test1...')

class Student(Person):
    def test(self):
        print(Student.num)#可继承下来
        # print(Student.__num1)  # 不能被继承下来

    def test3(self):
        print('test3...')
        # self.__test1() # 父类的私有方法是不能被继承下来的。
student = Student()
student.test3()#可继承下来

9、抽象类
之前我们定义了Person类实现了eat()、drink()方法,每种人都会吃喝,但是吃喝的地点不同,如果实现了方法体就浪费了。因此我们可以只定义eat()方法,不实现方法体,这种形式我们可以将方法定义为抽象方法,具有抽象方法的类就叫做抽象类。
抽象类是一个特殊的类,只能被继承,不能实例化,抽象类中可以有抽象方法和普通方法。
1)定义抽象类需要导入 abc模块。from abc import ABCMeta, abstractmethod
2)抽象方法:只定义方法,不具体实现方法体。
在定义抽象方法时需要在前面加入:@abstractmethod
抽象方法不包含任何可实现的代码,因此其函数体通常使用pass。

from abc import ABCMeta, abstractmethod
# 抽象类
class Animal(metaclass=ABCMeta):
    # 抽象方法
    @abstractmethod
    def eat(self): pass

    @abstractmethod
    def sleep(self): pass

    # 可以定义普通的方法。
    def play(self):
        print('拆家')

class Dog(Animal):

    def eat(self):#必须调用父类中的抽象方法
        print('吃狗粮...')

    def sleep(self):#必须调用父类中的抽象方法
        print('轻轻的睡觉')

dog = Dog()
dog.play()

注意:子类继承了抽象类父类,子类必须实现父类的抽象方法。
**

二、多继承

**
一个子类可以继承多个父类,就是多继承,并且拥有所有父类的属性和方法。
1、语法
class 子类名(父类名1,父类名2…) : pass

class A(object):
    num_a = 10

    def test1(self):
        print('A test1')

class B(object):
    num_b = 20

    def test2(self):
        print('B test2')

class C(A, B):
    pass
c=C
c.test1()
c.test2()

**2、**如果子类和父类有相同的方法,就会调用子类中的方法。如果不同的父类中存在着相同的方法名称,子类对象调用的时候会调用哪个父类中的方法呢? Python会根据 MRO(method resolution order) 方法解析顺序列表进行查找。

c = C()
c.test1()
print(C.mro())  # 使用 mro()方法 来查看类的搜索路径
print(C.__mro__)

3、继承原理
1)子类会先于父类被检查
2)多个父类会根据它们在列表中的顺序被检查
3)如果对下一个类存在两个合法的选择,选择第一个父类
在这里插入图片描述

4、多继承中super本质
不是直接查找父类,而是根据调用节点的广度优先顺序执行的。
在这里插入图片描述
与调用顺序刚好相反

三、多态特性

多态就是不同子类对象调用父类的方法产生不同的结果。
**例1、**使用不同支付工具给商店支付钱

import abc
class Pay(metaclass=abc.ABCMeta):#抽象类
      #抽象方法
    @abc.abstractmethod
    def pay(self, money): pass

class Alipay(Pay):
    def pay(self, money):
        print('支付宝到账{}元'.format(money))

class ApplePay(Pay):
    def pay(self, money):
        print('苹果支付{}元'.format(money))

class Person(object):
    def consumption(self, pay, money):#消费
        pay.pay(money)

alipay = Alipay()
apple_pay = ApplePay()
person = Person()
person.consumption(alipay,150)
person.consumption(apple_pay, 200)

例2、

from abc import ABCMeta, abstractmethod

class File(metaclass=ABCMeta):

    @abstractmethod
    def read(self): pass
    @abstractmethod
    def write(self): pass

class Word(File):
    def read(self):
        print('很优雅的读...')
    def write(self):
        print('很优雅的写...')

class Txt(File):
    def read(self):
        print('很大声的读...')
    def write(self):
        print('很夸张的写...')

猜你喜欢

转载自blog.csdn.net/qq_44240254/article/details/86498650