面向对象 Object Oriented
面向对象的学习:
- 面向对象的语法(简单,记忆就可以搞定)
- 面向对象的思想(稍难,需要一定的理解)
面向过程和面向对象的区别
面向过程开发,以函数作为基本结构使用:
吃饭 -> 吃饭的函数
喝水 -> 喝水函数
洗衣服 -> 洗衣服的函数
睡觉 -> 使用充气娃娃的函数
看电影 -> 买票开电影函数
....
面向对象的开发,以对象作为基本结构使用: 女朋友{ 喂饭功能 喂水功能 洗衣服功能 陪你睡觉功能 陪你看电影功能 .... }
吃饭->调用女盆友的喂饭功能
喝水->调用女朋友的喂水功能
洗衣服->调用女朋友的洗衣服功能
睡觉->调用女朋友的陪睡功能
...
面向对象的开发非常适合大型程序开发,开发速度和后期维护都比过程化开发要好很多。同时,也会降低一点效率。
语言中对象结构的特色:高内聚,低耦合。
面向对象相关的单词:
OO 面向对象
OOP 面向对象的程序开发
OOA 面向对象的分析
OOD 面向对象的设计
OOI 面向对象的实现
OOA -> OOD -> OOI 面向对象的实现过程
类和对象
什么是类
人类就是一个类
动物类也是一个类
鸟类就是一个类
女朋友也是一个类
基友也是一个类
瓶子都是一个类
类是一个实物的特征的集合,是抽象的概念。
打蛋蛋是一个类
XXOO也是一个类
撩妹也是一个类
开车也是一个类
打人也是一个类
类也是行为和操作的概念的集合。也是不具体的操作,没有真正操作过。
类是抽象的概念,仅此而已!
什么是对象
霍云瑞这个人他是一个对象
霍云瑞家的那个小鸡鸡是一个对象
霍云瑞的第一个女朋友就是一个对象
霍云瑞的当前的基友就是一个对象
这个瓶子就是一个对像。
教室后面那个空调就是一个对象。
对象就是具体存在的看得见摸得着的某个实物。
昨天霍云瑞打一次自己的蛋蛋,就是一个对象
今天中午霍云瑞吧马浚龙XXOO了就是一个对象
今天上午霍云瑞吧马俊龙撩了就是一个对象
马俊龙今天晚上把霍云瑞打了,这就是一个对象
真实发生过得行为就是对象
对象一定是具体的或者发生过的事物!
类和对象的关系
类是多个对象归纳总结而来的,是一种概念,包含所有对象。
由对象总结出类的过程,叫做抽象化
对象是类的具体实现或者实施而来,他是真实的,特指某个事物
由类制作出对象的过程,叫做实例化
如何书写类文件
推荐使用驼峰命名法来书写文件:
驼峰命名法:
类名:每个单词的首字母大写
人类 Person
开车 DriveCar
撩妹 LiaoMei
....
函数名/变量:除了第一个单词之外首字母大写
泷泽萝拉 longZeLuoLa
约炮函数 yuePao 或者yue_pao(不是驼峰命名)
一个文件如果是一个单独的类,那么直接使用类名来当作文件名即可
类的组成
类中只有2种内容:成员属性和成员方法
成员属性:
用于描述类的特征的变量就是成员属性
成员方法:
用于描述类的功能的函数就是成员方法
类的书写规则
1.必须使用class关键字来声明一个类
2.类的名称需要符合驼峰命名法(规范)
3.类中只能存在2种内容,成员属性和成员方法,除此之外,所有的代码都禁止出现!
4.声明成员属性时,所有成员属性必须有值,如果没值会报错!,推荐使用None等值代替
5.成员方法只需要按照函数的规则声明即可
实例化对象
实例化对象格式
对象变量 = 类()
类的类型为 type
<class 'type'>
类的值就是类本身
<class '__main__.Person'>
对象的类型为类
<class '__main__.Person'>
对象的值,对象本身
<__main__.Person object at 0x020DC650>
检测类和对象的成员
检测类成员
类名.__dict__
检测对象成员
对象.__dict__
类和对象成员的操作
类成员操作
访问类中成员
类名.成员属性名
类名.成员方法名() (没有参数要求,所有方法都可以通过类访问)
修改类中成员
类名.成员属性名 = 值
类名.成员方法名 = 新值 (如果需要函数只能用lambda)
删除类中成员
del 类名.成员属性名
del 类名.成员方法名
添加类中成员
类名.新成员属性名 = 值
类名.新成员方法名 = 值 (如果需要函数只能用lambda)
对象成员操作
访问对象中成员
对象变量.成员属性名
对象变量.成员方法名() (必须有一个用于接收对象本身的形参)
修改对象中成员
对象变量.成员属性名 = 值
对象变量.成员方法名 = 新值 (如果需要函数只能用lambda)
删除对象中成员
del 对象变量.成员属性名
del 对象变量名.成员方法名
添加对象中成员
对象变量.新成员属性名 = 值
对象变量.新成员方法名 = 值 (如果需要函数只能用lambda)
关于self
他不是关键字,是一个随意书写的字符串而已
1.英文单词的意义 :自己
2.绑定类的方法,只能通过类来访问的方法,就是绑定类的方法
3.非绑定类的方法,就是可以通过对象访问的方法就是非绑定的方法
4.绑定类与非绑定类的方法不取决于语法,而取决于设计者如何设计该方法
5.一般情况下非绑定类的方法第一个参数写单词self,但是这不是唯一的单词,写什么都行,self不是关键字,不是关键字,不是关键字!
面向对象的三大特性
面向对象都具有三大特性:封装,继承 和 多态
封装特性
封装就是对类和对象的成员访问进行限制,设定可以访问的方式和不可以访问的方式。
封装的三个级别:
私有化封装 -> private 英文单词而已不是关键字
受保护的封装 -> protected 英文单词而已不是关键字
公共的封装 -> public 英文单词而不是关键字
检测封装的三个位置:
类中/对象中
类外部/对象外部
子类中
私有化封装 private
私有化封装是最高级别的封装。私有化封装之后的成员,只能在类中/对象中访问,类的外部,子类中都不可以访问到。
私有化封装:在成员名称前添加2个_即可
例如:封装heart -> __heart
python将heart 改名为 _类名__成员名
封装后的访问限制:
类中/对象中 可以访问
类外/对象外 不可以访问
子类/子类对象 不可以访问
注意:在python中实现的封装操作,不是通过权限限制而是通过改名(name mangling 改名策略)实现的,名字变了找不到而已。
可以通过 对象.类名 __方法或类名.类名 __方法名访问到(但禁止这么干)
受保护的封装 protected
受保护的封装是一定级别的封装,封装之后,只有部分位置可以访问(类和子类),部分位置(类外)不可以访问。
受保护的封装: 在成员名称前添加1个_即可
例如:受保护 money -> _money
封装后的访问限制:
类中/对象中 可以访问
类外/对象外 可以访问(原则上类外不行,但是没实现)
子类/子类对象 可以访问
公共的封装 public
所有的成员默认都是公共的封装级别,可以在类中,类外,及子类中正常访问
类中/对象中 可以访问
类外/对象外 可以访问
子类/子类对象 可以访问
继承
继承就是可以获取另外一个类中的成员属性和成员方法。(并非所有成员)
作用:继承的作用是增加代码的复用性,节省不必要的重复代码,提高开发效率,同时可以设置类之间的关系。
继承的两个概念:
父类
用于被继承的类,称之为父类,也叫做基类,或者超类
子类
继承其他类的类,称之为子类,也叫做派生类
继承的格式
class 父类:
pass
class 子类(父类):#继承操作的关键步骤
pass
继承的特征
1.所有类都是继承自object类(object类对应的对象就是object对象,也是万物皆对象)
2.子类继承父类则可以访问父类的所有成员。(私有成员除外)
3.子类继承父类并不会将父类的所有成员复制到子类当中去,访问父类成员是间接通过父类来访问的,
4.子类可以具有自己独有的属性和方法
5.子类可以重载父类中的方法,只需要设置和父类指定成员相同的名称即可实现重载,重载之后的成员,子类只会访问当前类中的成员,而不会调用父类中同名的成员
6.子类中如果重载父类的方法,并且还想将重载的父类方法借调过来使用,可以在重载的方法中使用如下方法
[父类名.方法()](适合类) 或者 [super().方法()](适合对象)
单继承和多继承
单继承:每个类只能继承一个类的方式称为单继承。
多继承:每个类可以同时继承多个类的方式称为多继承。
python属于多继承语言!但是一般不用
多继承格式:
class 父类1:
pass
class 父类2:
pass
class 子类(父类1,父类2):
pass
多继承之后,子类就具备了所有父类的成员(私有成员除外)
多个父类具有相同的成员时,子类继承[继承列表]中第一个类的方法
菱形继承/钻石继承
菱形继承格式
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B,C):
pass
A
/
B C
/
D
菱形继承存在的问题
如果BC类同时继承了A类,D类又继承了BC两个类的情况下(菱形继承),
在调用BC中某个同名方法(该方法都继承自A类)时会导致继承自A类的该方法被多次调用。产生逻辑问题!
所以python使用 super() 类来解决了多继承的菱形继承问题
MRO列表
Method Realtion Order 用来制作一个继承关系的列表
python3中使用C3算法来计算MRO列表(计算过程暂时忽略)
MRO列表的制作原则:
1.子类永远在父类的前面
2.如果继承了多个父类,那么按照()中的顺序在列表中摆放
super()
super不是一个关键字,也是不是有函数,他是一个类
super()的作用不是查找父类,而是找MRO列表的上一个类
super()和父类没有任何实质性的关系,只是有时候能调用到父类而已。
在单继承的情况下,super()永远调用的是父类/父对象
格式:
super().方法() #python3的格式
多继承按需操作,在没有必要的时候避免强行使用!
mixin 设计模式
该设计模式的主要作用是采用多继承方式,进行类的扩展。
优点:
1.mixin可以在对类不做任何修改的情况下,扩展类的功能(添加父类)
2.可以方便的组织和维护各种不同组件的划分。
3.可以根据需要任意调整
4.可以避免创建更多的类,也可以避免继承导致的混乱
#水果类
class Fruit:
pass
#礼物类和非礼物类
class Gift:
pass
class NotGift:
pass
#南方北方类
class South:
pass
class North:
pass
#爽和不爽的苹果
class Cool:
pass
class NotCool:
pass
#真实水果类
class Apple(Fruit,Gift,North,NotCool):
pass
class Pear(Fruit,NotGift,North,NotCool):
pass
class Banana(Fruit,NotGift,North,Cool):
pass
class Orange(Fruit,Gift,South,NotCool)