面向对象之继承与多态

一. 继承(重要)

1.1 概念

  1. 什么是继承?

    继承就是新建类的一种方式,新建的类我们称为子类或者叫派生类,被继承的类我们称为父类或者基类,子类可以使用父类中的属性或者方法

  2. 为什么要用继承?

    类解决了对象与对象之间的代码冗余问题

    继承解决的是类与类之间的代码冗余问题

  3. 如何使用继承?

    新式类:继承了object类的子子孙孙类都是新式类

    经典类:没有继承了object类的子子孙孙类都是经典类

    ps:新式类和经典类只有在python2中区分

1.2 类的继承

image

1.3 单继承下属性查找

class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        #
        print('Foo.f2')
        self.f1()


class Bar(Foo):
    def f1(self):
        print('Bar.f1')


obj = Bar()  # {}
obj.f2()

image

练习:

class Foo:
    def __f1(self):  # _Foo__f1()
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.__f1()  # _Foo__f1()


class Bar(Foo):
    def __f1(self):  # # _Bar__f1()
        print('Bar.f1')


obj = Bar()  
obj.f2()

image

1.4 多继承下的属性查找

bases用法:

print(类名加_ _ bases _ _) 是查看该类所有的父类

image

image

# 新式类:按照广度优先查询
# 经典类:按照深度优先查询
class A(object):
    def test(self):
        print('from A')


class B(A):
    # def test(self):
    #     print('from B')
    pass

class C(A):
    # def test(self):
    #     print('from C')
    pass


class D(B):
    # def test(self):
    #     print('from D')
    pass

class E(C):
    # def test(self):
    #     print('from E')
    pass


class F(D, E):
    # def test(self):
    #     print('from F')
    pass


f1 = F()
f1.test()

1.5 super()

作用:super( ) 是调用父类的属性或方法

super()的应用场景:
子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找,我们既想使用父类的属性, 又想赋予子类新的属性,这时就需要使用super().

image

查找顺序也遵循mro列表

1.5 mro列表(了解)

对于你定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表,如下:

# mro列表练习2 
class B:
    def test(self):
        print('B---->test')

    def aaa(self):
        print('B---->aaa')

class A:
    def test(self):
        print('A---->test')
        super().aaa()


class C(A, B):
    def aaa(self):
        print('C----->aaa')


c = A()
# c.test()  # 打印结果:
print(A.mro())

image

三. 组合

在一个类中以另外一个类的对象作为数据属性,称为类的组合。组合与继承都是用来解决代码的重用性问题。不同的是:继承是一种“是”的关系,比如老师是人、学生是人,当类之间有很多相同的之处,应该使用继承;而组合则是一种“有”的关系,比如老师有生日,老师有多门课程,当类之间有显著不同,并且较小的类是较大的类所需要的组件时,应该使用组合,如下示例

class Course:
    def __init__(self,name,period,price):
        self.name=name
        self.period=period
        self.price=price
    def tell_info(self):
        print('<%s %s %s>' %(self.name,self.period,self.price))

class Date:
    def __init__(self,year,mon,day):
        self.year=year
        self.mon=mon
        self.day=day
    def tell_birth(self):
       print('<%s-%s-%s>' %(self.year,self.mon,self.day))

class People:
    school='清华大学'
    def __init__(self,name,sex,age):
        self.name=name
        self.sex=sex
        self.age=age

#Teacher类基于继承来重用People的代码,基于组合来重用Date类和Course类的代码
class Teacher(People): #老师是人
    def __init__(self,name,sex,age,title,year,mon,day):
        super().__init__(name,age,sex)
        self.birth=Date(year,mon,day) #老师有生日
        self.courses=[] #老师有课程,可以在实例化后,往该列表中添加Course类的对象
    def teach(self):
        print('%s is teaching' %self.name)


python=Course('python','3mons',3000.0)
linux=Course('linux','5mons',5000.0)
teacher1=Teacher('lili','female',28,'博士生导师',1990,3,23)

# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)

# 重用Date类的功能
teacher1.birth.tell_birth()

# 重用Course类的功能
for obj in teacher1.courses: 
    obj.tell_info()

QQ截图20211207190243

三. 多态与多态多样性

1. 什么是多态
水:液态水,固态水,气态水
动物:人,猪,狗,猫 ...



# 抽象类: 抽象类只能被继承,不能被实例化
class Animal(metaclass=abc.ABCMeta):

    @abc.abstractmethod  # 该方法已经是抽象方法了
    def speak(self): pass

    @abc.abstractmethod
    def login(self):pass

class People(Animal):
    def speak(self):
        # print('嗷嗷嗷')
        pass
    def login(self):
        pass


class Pig(Animal):
    def speak(self):
        print('哼哼哼')


class Dog(Animal):
    def speak(self):
        print('汪汪汪')


obj = People()
obj.speak()


# 多态练习
class Pig():
    def speak(self):
        print('哼哼哼')


class Dog():
    def speak(self):
        print('汪汪汪')

class Txt():
    def speak(self):
        print('Txt')

obj = People()
obj1 = Pig()
obj2 = Dog()
obj3 = Txt()

# 多态带来的特性:在不用考虑对象数据类型的情况下,直接调用对应的函数

def animal(animal):
    return animal.speak()

animal(obj)
animal(obj1)
animal(obj2)
animal(obj3)

# 父类限制子类的行为
class Animal():
    def speak(self):
        raise Exception("必须实现speak方法")
posted @ 2021-12-06 20:14  zong涵  阅读(45)  评论(0编辑  收藏  举报