CRPclass Person:
def __init__(self, name):
self.name = name
def talk(self):
pass
class Professor(Person):
def research(self):
"""研究"""
pass
def teaching(self):
"""教学"""
print(f"{self.name}正在讲高等数学")
class Teacher(Person):
def teaching(self):
"""教学"""
print(f"{self.name}正在讲小学算数")
def show(self):
"""表演"""
pass
class School:
def __init__(self, teacher):
# 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象
self.teacher = teacher
def attend_class(self):
self.teacher.teaching()
if __name__ == '__main__':
# 如果使用继承,就只能让教授或者老师其中一个来教书
# 如果学校只需要教书着一个功能,则继承对象的其他功能也被强制性的继承
t = Teacher("李毅")
s = School(t)
s.attend_class()
# 使用组合的方式,可以随时更换上课对象,同时也不会继承教师对象的其他方法和属性
t1 = Professor("杨勇")
s = School(t1)
s.attend_class()
李毅正在讲小学算数
杨勇正在讲高等数学
继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。
它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口。
复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。