#面向对象的特性# #封装# #继承# #多态#
1.面向对象的特性
面向对象编程有三个特性:封装、继承、多态
1.1 封装
面向对象的程序设计中,某个类把所需要的数据(也可以说是类的属性)和对数据的操作(也可以说是类的行为)全部都封装在类中,分别称为类的成员变量和方法(或成员函数)。这种把成员变量和成员函数封装在一起的编程特性称为封装
1.2 继承
继承是指可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展
1.3 多态
多态指的是一类事物有多种形态。如序列类型有多种形态:字符串,列表,元组;动物有多种形态:猫,狗,猪。多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作
2.封装
2.1 封装的概念
封装分为数据封装与方法封装。
- 数据封装:数据封装即把对象的属性具体的值隐藏起来,对外部显示的只是对象的属性名。比如张三的身高,钱包里的钱等
- 方法封装:方法封装即对外只需要通过方法名就能调用方法,而不需要了解具体方法中的细节。比如洗衣机,按洗衣的功能按钮,就能进行洗衣,我们不需要知道这个过程中的原理;在用支付宝进行付款的时候,只需要在用的时候把二维码给收款方或是扫一下收款方提供的二唯码就可以完成支付,不需要知道支付宝的支付接口,以及后台的处理数据的能力等
2.2 封装的作用
封装数据的主要原因是保护隐私;封装方法的主要原因是隔离复杂度
2.3 封装两个层面
- 第一层面的封装:第一层面的封装:创建类和对象时,分别创建两者的名称空间。只能通过类名加“.”或者对象的方式访问里面的名字
- 第二层面的封装:类中把某些属性和方法隐藏起来,或者定义为私有,只在类的内部使用,在类的外部无法访问,或者留下少量的接口(函数)供外部访问
3.继承
3.1 继承的概念
当我们定义一个class的时候,可以从某个现有的class 继承属性和方法,新的class称为子类,而被继承的class称为基类、父类或超类。
在python中,object类是所有类的父类。Python3中默认都是继承object,object类是顶级类或基类;其他⼦类叫做派⽣类。
# 括号为空,默认继承object
class 派生类名(object):
pass
3.2 继承的特点
- 在Python中,如果父类和子类都重新定义了构造方法
__init__
( ),在进行子类实例化的时候,子类的构造方法不会自动调用父类的构造方法,必须在子类中显示调用 - 如果需要在子类中调用父类的方法:需要以 父类名.方法 这种方式调用,以这种方式调用的时候,注意要传递self参数过去;另一种方法是使用super() ,直接使用 super().xxx
- Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)
- 对于继承关系,子类继承了父类所有的公有属性和方法,可以在子类中通过父类名来调用,而对于私有的属性和方法,子类是不进行继承的,因此在子类中是无法通过父类名来访问的
- Python支持多继承,能够让一个子类有多个父类:
- 如果有多个父类,多个父类名之间用逗号隔开,classSub(Super1,Super2)
- 如果子类没有重新定义构造方法
__init__
,它会自动调用第一个父类的构造方法,以第一个父类为中心 - 如果子类重新定义了构造方法
__init__
,需要显示去调用父类的构造方法,此时调用哪个父类的构造方法由你自己决定
3.3 继承的视线
3.3.1 单继承
编写一个Teacher(父类)和一个Student(子类),子类继承父类
class Teacher(object):def __init__(self, name, love):self.name = nameself.love = lovedef get_teacher_data(self):return f"大家好,我是老师{self.name}"class Student(Teacher):def __init__(self, name, love, name_stu):# 注意要显示调用父类的构造方法Teacher.__init__(self, name, love)self.name_stu = name_studef get_student_data(self):return f"我是学生{self.name_stu},老师是{self.name},我在学习{self.love}"if __name__ == '__main__':student = Student("张狂", "python", "张三")print(student.get_student_data())
执行结果
3.3.2 多继承
一个学生类同时继承两个老师类
class Teacher_First(object):def __init__(self, name_one, love_one):self.name_one = name_oneself.love_one = love_onedef get_teacher_one(self):return f"大家好,我是老师{self.name_one},我喜欢{self.love_one}"class Teacher_Second(object):def __init__(self, name_two, love_two):self.name_two = name_twoself.love_two = love_twodef get_teacher_two(self):return f"大家好,我是老师{self.name_two},我喜欢{self.love_two}"# 重新定义了构造方法__init__
class Student1(Teacher_First, Teacher_Second):def __init__(self, name_one, love_one, name_two, love_two, name_stu):# 注意要显示调用父类的构造方法Teacher_First.__init__(self, name_one, love_one)Teacher_Second.__init__(self, name_two, love_two)self.name_stu = name_studef get_student_data(self):return f"我是学生{self.name_stu},,我学会了{self.name_one}老师的{self.love_one}\和{self.name_two}老师的{self.love_two}"# 重没有新定义构造方法__init__,自动调用第一个父类的构造方法
class Student2(Teacher_First, Teacher_Second):def get_student_data(self):return f"我学会了{self.name_one}老师的{self.love_one}\和{self.name_two}老师的{self.love_two}"if __name__ == '__main__':student1 = Student1("张三", "python", "李四", "Java", "张三")print(student1.get_teacher_one())print(student1.get_teacher_two())print(student1.get_student_data())student2 = Student2("张三", "python") # 只能传第1个父类的构造方法,否则会报错# print(student2.get_teacher_two()) # 由于该类只能传第1个父类的构造方法,此方法被调用时内部参数未被传递,会报错# print(student2.get_student_data()) # 由于该类只能传第1个父类的构造方法,此方法被调用时部分内部参数未被传递,会报错
执行结果
4.多态
4.1 多态的概念
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数
4.2 多态的优点
调⽤灵活,有了多态,更容易编写出通⽤的代码,做出通⽤的编程,以适应需求的不断变化!
4.3 多态的实现步骤
- 定义⽗类,并提供公共⽅法
- 定义⼦类,并重写⽗类⽅法
- 传递⼦类对象给调⽤者,可以看到不同⼦类执⾏效果不同
# 定义⽗类,并提供公共⽅法
class Teacher(object):def get_data(self):pass# 定义⼦类,并重写⽗类⽅法
class Student_One(Teacher):def get_data(self):return "老师,我举报张三看漫画"# 定义⼦类,并重写⽗类⽅法
class Student_Two(Teacher):def get_data(self):return "老师,我举报李四玩游戏"class Main(object):def func_data(self, demo):return demo.get_data()stu1 = Student_One()
stu2 = Student_Two()main = Main()
# 传递⼦类对象给调⽤者,可以看到不同⼦类执⾏效果不同
# 传入不同的对象,实现不同的方法
print(main.func_data(stu1))
print(main.func_data(stu2))
执行结果