类与类之间的关系

  ⼤千世界, 万物之间皆有规则和规律. 我们的类和对象是对⼤千世界中的所有事物进行归
类. 那事物之间存在着相对应的关系. 类与类之间也同样如此. 在⾯向对象的世界中. 类与类
中存在以下关系:
  1. 依赖关系
  2. 关联关系
  3. 组合关系
  4. 聚合关系
  5. 继承关系
  6. 实现关系
  由于python是⼀门弱类型编程语言. 并且所有的对象之间其实都是多态的关系. 也就是说,
所有的东⻄都可以当做对象来使用. 所以我们在写代码的时候很容易形成以上关系. ⾸先. 我
们先看第一种, 也是这些关系中紧密程度最低的一个, 依赖关系.

# 写一个植物大战僵尸
# 1. 植物
#       打僵尸. 僵尸掉血
# 2. 僵尸
#       吃植物. 植物掉血class Plant:def __init__(self, name, hp, ad): # 200self.name = nameself.hp = hpself.ad = addef attack(self, js):print("植物攻击僵尸")js.hp -= self.adprint(f"僵尸掉血{self.ad}, 还剩下{js.hp}")class JiangShi:def __init__(self, name, hp, ad): # 1000  800self.name = nameself.hp = hpself.ad = addef attack(self, zw):print("僵尸咬植物")zw.hp -= self.adprint(f"植物掉血{self.ad}, 还剩{zw.hp}")# 植物
wd = Plant("歪脖子豌豆", 10, 20)
# 僵尸
js = JiangShi("铁桶僵尸", 200, 1)
wd.attack(js)
wd.attack(js)
wd.attack(js)
wd.attack(js)
wd.attack(js)js.attack(wd)
js.attack(wd)
js.attack(wd)
js.attack(wd)
# 攻击僵尸
# 僵尸掉血20, 还剩下180
# 植物攻击僵尸
# 僵尸掉血20, 还剩下160
# 植物攻击僵尸
# 僵尸掉血20, 还剩下140
# 植物攻击僵尸
# 僵尸掉血20, 还剩下120
# 植物攻击僵尸
# 僵尸掉血20, 还剩下100
# 僵尸咬植物
# 植物掉血1, 还剩9
# 僵尸咬植物
# 植物掉血1, 还剩8
# 僵尸咬植物
# 植物掉血1, 还剩7
# 僵尸咬植物
# 植物掉血1, 还剩6

我用着你. 但是你不属于我. 这种关系是最弱的.
比如. 公司和雇员之间. 对于正式员⼯, 肯定要签订劳动合同. 还得⼩心伺候着. 但是如果是兼
职. 那无所谓. 需要了你就来. 不需要你就可以拜拜了. 这里的兼职(临时工) 就属于依赖关系.
我用你. 但是你不属于我.

首先, 我们设计一个场景. 还是最初的那个例子. 要把大象装冰箱. 注意. 在这个场景中, 其
实是存在了两种事物的. ⼀个是大象, ⼤象负责整个事件的掌控者, 还有⼀个是冰箱, 冰箱负
责被大象操纵.
⾸先, 写出两个类, ⼀个是大象类, 一个是冰箱类.

class Elphant:def __init__(self, name):self.name = namedef open(self):'''开⻔return:'''passdef close(self):'''关⻔:retrrn:'''pass
class Refrigerator:def open_door(self):print("冰箱⻔门被打开了了")def close_door(self):print("冰箱⻔门被关上了了")                

  冰箱的功能非常简单, 只要会开门, 关⻔就行了. 但是大象就没那么简单了. 想想. 大象开
门和关⻔的时候是不是要先找个冰箱啊. 然后呢? 打开冰箱门. 是不是打开刚才找到的那个冰
箱⻔. 然后装⾃己. 最后呢? 关冰箱门, 注意, 关的是刚才那个冰箱吧. 也就是说. 开门和关门
用的是同⼀个冰箱. 并且. 大象有更换冰箱的权利, 想进那个冰箱就进那个冰箱. 这时, ⼤象类
和冰箱类的关系并没有那么的紧密. 因为大象可以指定任何一个冰箱. 接下来. 我们把代码完
善⼀下.

此时, 我们说, ⼤象和冰箱之间就是依赖关系. 我用着你. 但是你不属于我. 这种关系是最弱的.
比如. 公司和雇员之间. 对于正式员工, 肯定要签订劳动合同. 还得⼩心伺候着. 但是如果是兼
职. 那无所谓. 需要了你就来. 不需要你就可以拜拜了. 这里的兼职(临时工) 就属于依赖关
我用你. 但是你不属于我.

关联关系  .组合关系,   聚合关系

其实这三个在代码上写法是一样的. 但是, 从含义上是不一样的.

  1. 关联关系. 两种事物必须是互相关联的. 但是在某些特殊情况下是可以更改和更换的.

  2. 聚合关系. 属于关联关系中的一种特例. 侧重点是xxx和xxx聚合成xxx. 各⾃有各自的
生命周期. 比如电脑. 电脑里有CPU, 硬盘, 内存等等. 电脑挂了. CPU还是好的. 还是
完整的个体

  3. 组合关系. 属于关联关系中的一种特例. 写法上差不多. 组合关系比聚合还要紧密. 比如⼈的⼤脑, ⼼脏, 各个器官. 这些器官组合成⼀个人. 这时. 人如果挂了. 其他的东⻄也跟着挂了

  首先我们看关联关系:

这个最简单. 也是最常用的⼀种关系. 比如. 大家都有男女朋友. 男人

关联着女朋友. 女人关联着男朋友. 这种关系可以是互相的, 也可以是单⽅的.

class Boy:def __init__(self, name,  girlFriend=None):# 在初始化的时候可以给一个对象的属性设置成另一个类的对象self.girlFriend = girlFriend  # 一个男孩有一个女朋友def chi(self):if self.girlFriend:print(f"带着他的女朋友{self.girlFriend.name}去吃饭")else:print("单身狗, 吃什么吃? 滚去学习.")def movie(self):if self.girlFriend:print(f"带着他的女朋友{self.girlFriend.name}去看电影")else:print("单身狗, 看什么看? 滚去学习.")
class Girl:def __init__(self, name):self.name = nameb = Boy("宝浪")
g = Girl("孙艺珍")
b.chi()# alex给包浪介绍了一个女朋. 孙艺珍
b.girlFriend = g
b.chi()g2 = Girl("梁咏琪")
b.girlFriend = g2 # 换了个女朋友
b.chi()
# 单身狗, 吃什么吃? 滚去学习.
# 带着他的女朋友孙艺珍去吃饭
# 带着他的女朋友梁咏琪去吃饭

  注意. 此时Boy和Girl两个类之间就是关联关系. 两个类的对象紧密练习着. 其中一个没有
了. 另一个就孤单的不得了. 关联关系, 其实就是 我需要你. 你也属于我. 这就是关联关系. 像
这样的关系有很多很多. 比如. 学校和老师之间的关系.
School --- 学校
Teacher--- 老师
老师必然属于⼀个学校. 换句话说. 每个老师肯定有⼀个指定的工作机构. 就是学校. 那老师
的属性中必然关联着学校.

class School:def __init__(self, name):self.teach_list = [] # 这里要装多个老师self.name = namedef zhaopin(self, teach):self.teach_list.append(teach)def shangke(self):for t in self.teach_list:t.work()class Teacher:def __init__(self, name):self.name = namedef work(self):print(f"{self.name}在上课")lnh = School("老男孩")
t1 = Teacher("武sir")
t2 = Teacher("太白")
t3 = Teacher("哪吒")
t4 = Teacher("女神")
t5 = Teacher("日天")
t6 = Teacher("宝浪")lnh.zhaopin(t1)
lnh.zhaopin(t2)
lnh.zhaopin(t3)
lnh.zhaopin(t4)
lnh.zhaopin(t5)
lnh.zhaopin(t6)lnh.shangke()
# 武sir在上课
# 太白在上课
# 哪吒在上课
# 女神在上课
# 日天在上课
# 宝浪在上课

  好了. 这就是关联关系. 当我们在逻辑上出现了. 我需要你. 你还得属于我. 这种逻辑 就是关
联关系. 那注意. 这种关系的紧密程度比上面的依赖关系要紧密的多. 为什么呢? 想想吧
至于组合关系和聚合关系. 其实代码上的差别不⼤大. 都是把另一个类的对象作为这个类的
属性来传递和保存. 只是在含义上会有些许的不同而已.

继承关系

  在⾯向对象的世界中存在着继承关系. 我们现实中也存在着这样的关系. 我们说过. x是一
种y, 那x就可以继承y. 这时理解层面上的. 如果上升到代码层面. 我们可以这样认为. 子类在不
影响父类的程序运行的基础上对父类进行的扩充和扩展. 这里.我们可以把父类被称为超类或
者基类. 子类被称为派生类
首先, 类名和对象默认是可以作为字典的key的

class Foo:passprint(hash(Foo)) # 可哈希
##-9223371886657599443print(hash(Foo()))
##150199209592
# 我们写好的类和创建的对象默认都是可哈希的# 去掉可哈希
class Foo:__hash__ = None # 当前类的对象不可哈希print(hash(Foo)) # 可哈希
# -9223371886657599384# print(hash(Foo())) # TypeError: unhashable type: 'Foo'不可哈希class Foo:def chi(self, food):print("我爱吃鱼和", food)class Bar:def chi(self, food):print("我爱吃肉和", food)dic = {Foo: "鸡蛋", Bar: "香肠"}for k, v in dic.items():k().chi(v)
# 我爱吃鱼和 鸡蛋
# 我爱吃肉和 香肠类名和对象默认是可以作为字典的key的

  接下来. 我们来继续研究继承上的相关内容. 在本节中主要研究一下self. 记住. 不管方法之
间如何进行调用. 类与类之间是何关系. 默认的self都是访问这个⽅法的对象.

class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)
class Foo(Base):pass
obj = Foo(123)
obj.func1()
#123

class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)class Foo(Base):def func1(self):print("Foo. func1", self.num)obj = Foo(123)
obj.func1()
# # Foo. func1 123
# 

class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)self.func2()def func2(self):print("Base.func2")class Foo(Base):def func2(self):print("Foo.func2")
obj = Foo(123)
obj.func1()
##123

总结. self在访问方法的顺序: 永远先找自己的. ⾃己的找不到再找⽗类的.

class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)self.func2()def func2(self):print(111, self.num)class Foo(Base):def func2(self):print(222, self.num)lst = [Base(1), Base(2), Foo(3)]
for obj in lst:obj.func2()
##111 1
##111 2
##222 3

class Base:def __init__(self, num):self.num = numdef func1(self):print(self.num)self.func2()def func2(self):print(111, self.num)class Foo(Base):def func2(self):print(222, self.num)lst = [Base(1), Base(2), Foo(3)]
for obj in lst:obj.func1()# 1
# 111 1
# 2
# 111 2
# 3
# 222 3

结论: self就是你访问方法的那个对象. 先找⾃己, 然后在找父类的.

类中的关系: 依赖关系是最轻的. 最重的是继承关系. 关联关系是比较微妙的.

self到底是谁?
self:谁调用的就是谁. 类型是根据调用方的对象来进行变换的
super:表示的是父类

类中的特殊成员

什么是特殊成员呢? __init_()就是一个特殊的成员. 说白了. 带双下划线的那一坨. 这些方
法在特殊的场景的时候会被自动的执行. 比如,
1. 类名() 会自动执行__init__()
2. 对象() 会⾃动执行__call__()
3. 对象[key] 会⾃动执行__getitem__()
4. 对象[key] = value 会自动执行__setitem__()
5. del 对象[key] 会⾃动执行 __delitem__()
6. 对象+对象 会⾃动执行 __add__()
7. with 对象 as 变量 会自动执行__enter__ 和__exit__
8. 打印对象的时候 会自动执行 __str__
9. 干掉可哈希 __hash__ == None 对象就不可哈希了了.

...

......

.........

 

特殊成员:
__init__() # 创建对象的时候初始化操作
__call__() # 对象()
__getitem__() # 对象[哈哈]
__setitem__() # 对象[哈哈] = 值
__new__() # 创建对象的时候.开辟内存
__enter__() # with 对象
__exit__() #结束with的时候
__hash__() # 可哈希 hash()

创建对象的真正步骤:
  首先, 在执行类名()的时候. 系统会自动先执行__new__()来开辟内存. 此时新开辟出来的内
存区域是空的. 紧随其后, 系统⾃动调⽤__init__()来完成对象的初始化工作. 按照时间轴来算.
  1. 加载类
  2. 开辟内存(__new__)
  3. 初始化(__init__)
  4. 使⽤用对象⼲干xxxxxxxxx
类似的操作还有很多很多. 我们不需要完全刻意的去把所有的特殊成员全都记住. 实战中也
用不到那么多. 用到了查就是了.

面向对象编程的执行流程 ->
  1. 加载类 -> 给类创建一个名称空间 -> 主要存放类变量.
  2. 创建对象 -> 先找类. -> 根据类来开辟内存 ->

  执行类中的__new__() -> 执行__init__() -> 返回对象

class Foo:def __init__(self): # 初始化操作print("我是init,  我是老二")print("初始化操作. 在创建对象的时候自动调用这个方法")def __new__(cls, *args, **kwargs): # 创建, 它是真正的构造方法,  可以开辟内存print("我是new. 我是老大")return object.__new__(cls)# 为了 对象()def __call__(self, *args, **kwargs):print("我是对象()")# 对象[]def __getitem__(self, item):print("item=",item)print("你执行了__getitem__")return "哈哈"# 对象[key] = valuedef __setitem__(self, key, value):print("key, ", key)print("value, ", value)# del lst[1]def __delitem__(self, key):print("key=", key)# with 对象:def __enter__(self):print("我是enter")# with 对象: 代码执行完毕. 最后执行这里def __exit__(self, exc_type, exc_val, exc_tb):print("我叫exit")def __len__(self):print("我的天哪")return 3f = Foo()    # 自动执行__init__()
f()     # 调用-> __call__()
print(callable(f)) # 对象()print(f["李嘉诚"]) # 自动调用__getitem__()
f['jay'] = "林俊杰"del f['哈哈']with f:print("我是哈哈哈哈")with open() :lst = ["孙艺珍", "李金珠", "井柏然"]lst[2] # =>自动的调用__getitem__()def func():pass
func = 3
print(callable(func)) # 判断xxx是否是可调用的
f.__init__()  # 第一次这么写. 以后别这么写
lst = [1,2,3,4]
it = iter(lst)print(it.__next__())print(next(it)) # __next__()

面试之前翻一番
写出15个特殊成员, 并给出具体作用

转载于:https://www.cnblogs.com/H1050676808/p/10145672.html

类与类之间的关系:依赖关系和关联关系及继承关系中self是什么? 类里面的特殊成员...相关推荐

  1. 关联关系,继承关系,多态

    文章目录 关联关系 继承关系 类装饰器 多态 单例模式 关联关系 知识点: 1.has a 一个类中使用了另一个自定义的类型 student使用了computer book 2.类型 系统类型: st ...

  2. java怎么快速创建监听类_java_利用java监听器实现在线人数统计,1.在工程中创建监听类SessionLi - phpStudy...

    利用java监听器实现在线人数统计 1.在工程中创建监听类SessionListener 并且实现HttpSessionListener接口,代码如下 import javax.servlet.htt ...

  3. UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现

    类与类图 1) 类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性.操作.关系的对象集合的总称. 2) 在系统中,每个类具有一定的职责,职责指的是类所担任的任务,即类要完成什 ...

  4. 转:UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现

    转:UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现 原文:https://www.cnblogs.com/firstcsharp/p/5327659.html 类与类图 1) 类(Clas ...

  5. idea中查看类的继承关系图

    快捷键CTRL+H查看 利用idea快捷键查看hierarchy,效果如下 好处:可以看向上和向下的继承关系 缺点:只能看继承关系,不能看实现了哪些接口 在指定类右键查看diagram 也可以使用快捷 ...

  6. python新式类c3算法_Python 新式类继承关系的 C3 算法(Python 2.3 的方法解析顺序,MRO)...

    Python 新式类继承关系的 C3 算法(Python 2.3 的方法解析顺序,MRO) 翻译:刘硕 摘要:本文档面向于想要了解Python 2.3版本中 C3 方法解析顺序的 Python程序开发 ...

  7. VC++中使用使用winnet类获取网页内容

    2005-09-01 VC++中使用使用winnet类获取网页内容 - [VC专栏] 微软提供的Winnet类是一个应用层的网络通信组件, 它可以使你的应用程序很容易的实现http.ftp.gophe ...

  8. java集合类继承关系图_java集合继承关系图

    面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 数组虽然也可以存储对象,但长度是固定的:集合长度是可变的,数组中可以存储基 ...

  9. 一个java程序中什么是主类_下列哪个是Java应用程序主类中正确的main方法?_学小易找答案...

    [判断题]用佛尔哈德法测定Ag + 时,不用先除去氮的低价氧化物.汞盐等杂质. [单选题]下列哪个是Java应用程序主类中正确的main方法? [判断题]javac.exe 命令文件存放在 JDK 安 ...

最新文章

  1. ORB-SLAM2地图存储加载系统
  2. 整合Hibernate3.x
  3. FZU - 2042 The Mad Mathematician 数位dp + 算贡献
  4. 电影与爆米花(模拟)
  5. 荣耀30 Pro Geekbench跑分现身:麒麟990 5G SoC性能出众
  6. 「爬虫入门」拒绝跟热点搞python,直接在浏览器里体验『第一次』,理解原理=>如鱼得水
  7. libtoolize: 未找到命令
  8. xml文件中servlet映射重复问题,也是导致tomcat启动不了,出现在Java 9上运行时,需在JVM命令行参数中添加“-add opens=Java.base/Java.lang=ALL-U
  9. linux批量化删除以某某结尾命令
  10. Flink(三十七)—— Flink 清理过期 Checkpoint 目录的正确姿势
  11. 二维几何图形创作方法(Geometry2D)
  12. 离散数学复习:二元关系
  13. JS中1900-2100区间内的公历、农历互转的工具类
  14. 关于表情识别-综述 FER --FER2013
  15. 【微信小程序导入项目报错:[app.json文件内容错误]app.json未找到】解决方法
  16. java毕业设计——基于java+Jsoup+HttpClient的网络爬虫技术的网络新闻分析系统设计与实现(毕业论文+程序源码)——网络新闻分析系统
  17. C++骰子游戏课程设计(含源码)
  18. 想拥有自己说了算的人生,必须要有的三层智慧
  19. tableau制作凹凸图(超市各年份利润)
  20. 大数据获客系统及源码5

热门文章

  1. tab weui 页面切换_weui tabbar 切换
  2. onKeyDown方法笔记
  3. java计算机毕业设计环巢湖区域旅游网站源码+mysql数据库+系统+lw文档+部署
  4. 农业品牌进行展会招商时最易犯的六种错误
  5. centos8 stream 百度网盘
  6. opencv获取外接摄像头_opencv获取摄像头视频
  7. 南职计算机专业是热门吗,计算机专业现在还是热门专业吗?
  8. CTFSHOW 新生杯web
  9. 再见c罗再见梅西_再见亨利·福特,您好开放组织
  10. Java、两个矩阵相乘