派生与组合

# 派生与方法重用

# 子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找

class People:
    school = '清华大学'

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age


class Teacher(People):
    def __init__(self, name, sex, age, title):  # 派生
        self.name = name
        self.sex = sex
        self.age = age
        self.title = title

    def teach(self):
        print('%s is teaching' % self.name)


obj = Teacher('lili', 'female', 28, '高级讲师')  # 只会找自己类中的__init__,并不会自动调用父类的
print(obj.name, obj.sex, obj.age, obj.title)  # ('lili', 'female', 28, '高级讲师')


# 很明显子类Teacher中__init__内的前三行又是在写重复代码,若想在子类派生出的方法内重用父类的功能,有两种实现方式

# 方式一:“指名道姓”地调用某一个类的函数=》不依赖于继承关系
class Teacher(People):
    def __init__(self, name, sex, age, title):
        People.__init__(self, name, age, sex)  # 调用的是函数,因而需要传入self

    def teach(self):
        print('%s is teaching' % self.name)


# 方式二:super()调用父类提供给自己的方法=》严格依赖继承关系
#        调用super()会得到一个特殊的对象,该对象会参照发起属性查找的那个类的mro,去当前类的父类中找属性
class Teacher(People):
    def __init__(self, name, sex, age, title):
        super().__init__(name, age, sex)  # 调用的是绑定方法,自动传入self

    def teach(self):
        print('%s is teaching' % self.name)


# 这两种方式的区别是:
# 方式一是跟继承没有关系的,
# 方式二的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找

class A:
    def test(self):
        super().test()


class B:
    def test(self):
        print('from B')


class C(A, B):
    pass


print(C.mro())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
c = C()
print(c.test())
'''
c.test()首先找到A下的test方法,执行super().test()会基于MRO列表当前所处的位置继续往后查找,然后在B中找到了test方法并执行。
'''

# 组合
'''
在一个类中以另外一个类的对象作为数据属性,称为类的组合。组合与继承都是用来解决代码的重用性问题。
不同的是:继承是一种”是“的关系,比如老师是人、学生是人。当类之间有很多相同之处,应该是有继承;而组合则是一种”有“的关系
比如老师有生日,老师有多门课程,当类之间有显著不同,并且较小的类是较大的类所需要的组件时,应该使用组合
'''
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()
posted @ 2021-01-26 10:45  啦啦哦  阅读(111)  评论(0编辑  收藏  举报