昨天我介绍了继承,它是描述类与类之间什么是什么的关系,它的作用就是减少代码冗余,但是它是强耦合
而今天我们介绍了另一种解决类与类之间代码冗余的方式
组合
什么是组合那?
描述的是类与类之间的关系,是一种什么有什么的关系
一个类产生的对象,该对象拥有一个属性 这个属性的值是来自于另外一个类的对象
# 组合 # 举个例子来说明继承和组合的区别 # 代码冗余的 class Teacher: def __init__(self,name,age,sex,leven,salary,year,mon,day): self.name=name self.age=age self.sex=sex self.leven=leven self.salary=salary self.year=year self.mon=mon self.day=day def inter(self): print('讲课,改分') def info(self): print(''' 年:%s 月:%s 日:%s '''%(self.year,self.mon,self.day)) class Student: def __init__(self,name,age,sex,id,year,mon,day): self.name=name self.age=age self.sex=sex self.id=id self.year=year self.mon=mon self.day=day def inter(self): print('学习,选课') def info(self): print(''' 年:%s 月:%s 日:%s '''%(self.year,self.mon,self.day)) tea=Teacher('lxx',18,'man',10,30000,2000,1,1) tea.info() stu=Student('wxx',16,'man',10086,2002,3,3) stu.info() # 继承 class Oldboypeople: def __init__(self,name,age,sex,year,mon,day): self.name=name self.age=age self.sex=sex self.year=year self.mon=mon self.day=day def info(self): print(''' 年:%s 月:%s 日:%s '''%(self.year,self.mon,self.day)) class Teacher(Oldboypeople): def __init__(self,name,age,sex,year,mon,day,leven,salary): super().__init__(name,age,sex,year,mon,day) self.leven=leven self.salary=salary def inter(self): print('学习,选课') class Student(Oldboypeople): def __init__(self,name,age,sex,year,mon,day,id): super().__init__(name,age,sex,year,mon,day) self.id=id def inter(self): print('学习,选课') tea1=Teacher('lxx',18,'man',30000,2000,1,1,10) tea1.info() stu1=Student('wxx',16,'man',2002,3,3,10086) stu1.info() # 组合 class Date: def __init__(self,year, mon, day): self.year = year self.mon = mon self.day = day def info(self): print(''' 年:%s 月:%s 日:%s ''' % (self.year, self.mon, self.day)) class Oldboypeople: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class Teacher(Oldboypeople): def __init__(self,name,age,sex,leven,salary): super().__init__(name,age,sex,) self.leven=leven self.salary=salary def inter(self): print('学习,选课') class Student(Oldboypeople): def __init__(self,name,age,sex,id): super().__init__(name,age,sex) self.id=id def inter(self): print('学习,选课') tea1=Teacher('lxx',18,'man',30000,2000,) stu1=Student('wxx',16,'man',2002,) dat=Date(2000,3,3) tea1=dat tea1.info() stu1=dat stu1.info()
封装
什么是封装?
装就是一堆属性存在起来,封的概念就把这些属性给隐藏起来
class 类名: __属性名=2 赋值给一个名字=类名() print(赋值给一个名字.x)
#会报错误
SyntaxError: invalid syntax
__属性=_类名__属性名
举些实际例子
class Teacher: __x=2 tea=Teacher() print(tea.x) class Teacher: def __x(self): print('x') tea=Teacher() tea.x() class Teacher: def __init__(self,name): self.__name=name tea=Teacher('lxx') print(tea.__name)
这些就是封装的实际例子 但是有些人会发现你调的都是__x 定义的确是x 请看下面
class Teacher: __x=2 tea=Teacher() print(tea.__x) #依然会报错 Traceback (most recent call last): File "C:/Users/64802/PycharmProjects/kaoshi/学习/学习/day21/组合与分装.py", line 122, in <module> print(tea.__x) AttributeError: 'Teacher' object has no attribute '__x'
其实这种隐藏只是一种语法上的变形
注意:1.为一个属性名加__开头,会在类定义阶段将属性名变形
2.这种语法意义上变形,只在类的定义阶段发生一次,类定义之后,新增__开头的属性都没有变形的效果
3.如果父类不想让子类覆盖自己 就可以用__开头的方法
#父类不想被子类覆盖 #会被覆盖 class Father: def f1(self): print('Father f1') class Sun(Father): def f1(self): print('Sun f1') res=Sun() res.f1()#Sun f1 #用__开头不会被覆盖 class Father: def f1(self): print('Father f1') class Sun(Father): def __f1(self): print('Sun f1') res=Sun() res.f1()#Father f1
搞清楚封装是怎么回事,我们就会产生疑问 ???
既然你要藏起来它 你还定义它干嘛!!!(但凡定义了说明我们需要用到它)
这就说明了封装不是单纯的隐藏
我们先不说封装到底是干什么的 来举个例子
class Oldboypeople: def __init__(self,name,age,sex): self.__name=name self.__age=age self.__sex=sex def info(self): name=input('想学的课程,我们为你介绍我们的金牌讲师>>:').strip() if name=='q': return print(''' 性别:%s 年龄:%s 性别:%s '''%(self.__name,self.__age,self.__sex)) class Teacher(Oldboypeople): def __init__(self,name,age,sex,leven,salary): super().__init__(name,age,sex,) self.leven=leven self.salary=salary tea1=Teacher('lxx',18,'man',30000,2000,) tea1.info() print(tea1.leven)
我们把信息隐藏起来了,类外面无法直接调用,这样我们就可以设计个接口 通过这个接口来调用信息,因为想调用信息必须经过接口 所以我们就可以肆意的加条件,有点相似于我们刘老师之前讲的写程序分层,也符合我们上帝是的思维方式这就是封装的作用
总结一下:
封装数据属性的目的:为了隔离复杂度,把数据属性封装起来,然后需要开辟接口给类外部的使用者使用,好处是我们可以在接口之上添加逻辑从而严格空间访问者对属性的操作
终极奥义:明确的区分内外,对外隐藏的,对内是开放的
所谓内是一个类内 不包括其子类,简单粗暴的说就是这个类以外 全部都是外