面向对象 - 继承
什么是继承?
继承是面向对象的特征之一,编程语言中的固定语法,用于将一个类继承到另一个类,实现类中代码的复用。
出现继承之后,两个类直接的关系如下:
- 父类: 被继承的类,父类中的代码会被重复利用
- 也叫 超类(超级类型) 、 基类(基础类型) 、 代码中通过
super
表示
- 也叫 超类(超级类型) 、 基类(基础类型) 、 代码中通过
- 子类: 当前类型,继承父类 可以直接适用父类中的 非私有属性 和 非私有 方法
函数 的出现,实现了代码块的服用
模块 的出现,实现了模块内部代码的复用
继承 的出现,实现了类的复用
代码实现继承
1. 继承是怎么体现的?
人 - 类
男人 - 类
男人 继承 人 -> 男人 是 人 -> 男人 is 人
2. 代码实现继承
class 父类:
def __init__(self):
父类中的属性
def 父类中的方法(self):
pass
class 子类(继承的父类名称):
pass
==============================
class Person:
def __init__(self, name):
self.name = name
class Man(Person):
"""子类:男人类型 继承了Person"""
pass
一个类继承其它类,要将继承的类名称填写在类声明后边的括号中,如果一个类后边不写括号,默认继承
object
类型。 Python中所有的类都是直接或者间接继承自 object
继承的好处?
继承的好处,不仅仅在与重复利用了父类中的非私有属性和方法,同时可以在当前自己的类中完成功能的扩展,提供高能的扩展性。
- 重复使用父类中(非私有)的属性和方法
- 子类中扩展新的功能
class Person:
"""定义一个人 类"""
def __init__(self, name, age):
"""定义一个初始化方法"""
self.name = name
self.age = age
def eat(self):
"""定义一个吃饭的方法"""
print(f"{self.name}在吃饭...")
class Teacher(Person):
"""定义一个老师的类 继承自 Person"""
def tech(self):
"""子类中定义一个 教书的方法"""
print(f"{self.name}在教书...")
damu = Teacher("damu", 18)
damu.eat() # 子类继承父类的功能
# damu在吃饭...
damu.tech() # 子类对父类功能的扩展
# damu在教书...
适用场景
1.什么时候适用继承
项目中出现了多个相似的类型(管理员,会员,用户等),对应的数据中出现了相同的代码(属性,方法),此时就需要考虑是否通过继承,完成代码的复用性提升!
2.继承关系中,继承什么数据?
Python中的类包含 :
- 公共的属性和方法
- 受保护的属性和方法 [属性或者方法前有一个
_
标识] - 私有的属性和方法
继承关系中,子类会继承父类中公共的属性和方法,受保护的属性和方法可以继承但是 IDE工具中会有警告提示,私有的属性和方法理论上不能继承!
方法重写
子类中编写和父类相同的代码
-
属性相同:就是软件设计上的问题
需要重构,父类中的属性,子类可以继承过来,不需要在重新编写 -
方法相同:是继承中的一个功能扩展特性 [方法重写]
- 子类中重新声明编写父类中已有的方法,完成功能的扩展
- 代码运行过程中,如果子类中重写了父类中的方法,只会执行子类中的方法
方法重写的好处
- 子类可以根据自己的特殊情况,重新定义父类中声明的方法,调用时就会执行子类中重写的方法,完成功能的改造
- 子类可以重写父类的方法,在方法中主动调用父类的方法,达到功能扩展的目的
class Gun:
"""定义一个枪械类"""
def __init__(self, name):
self.name = name
def fire(self):
"""定义一个开火的方法"""
print(f"{self.name}开火了...")
class Ak47(Gun):
"""定义一个ak47类 继承自 Gun"""
def fire(self):
"""重写父类中开火的方法"""
print(f"{self.name}哒哒哒地开火了...")
class M4A1(Gun):
"""定义一个M4a1类 继承自 Gun"""
def fire(self):
"""重写父类中开火的方法"""
# 在父类 fire()方法的基础上增添新功能
print("安装上8倍镜..")
print("安装上消音器..")
# 调用父类中的 fire() 方法
super().fire()
print("一枪制敌!")
m4 = M4A1("M4A1")
ak = Ak47("AK47")
ak.fire()
# AK47哒哒哒地开火了...
m4.fire()
# 安装上8倍镜..
# 安装上消音器..
# M4A1开火了...
# 一枪制敌!
访问父类方法
调用父类中不同的方法:
-
__特殊方法__()
super().__特殊方法__()
调用父类中的方法
-
__私有方法()
- 子类无法调用
-
普通方法()
super().普通方法()
调用父类中的方法
为什么要调用父类方法
子类通过方法重写,重写了父类中的方法,此时父类的方法就不会执行了
如果子类的方法中需要适用父类方法的功能,就可以通过上述方式主动调用父类中的方法
多继承
代码实现 - 多继承
# 通过在类声明的后边,添加连续的多个父类,完成多继承模式
class Person(Son, Husband, Dad, Employee, Teacher):
"""人的类型:同时继承多个类型"""
pass
判断对象输入某个类
damu = Person()
isinstance(damu, Person)
# True
多继承中的问题
如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用哪一个父类中的方法呢?
Python中针对 类 提供了一个内置属性 mro 可以查看方法的搜索顺序
print(类.__mro__)
# (<class '__main__.Son'>, <class '__main__.Dad'>, <class '__main__.Mom'>, <class 'object'>)
- 在搜索方法时,是按照
__mro__
的输出结果 从左至右 的顺序查找的 - 如果在当前类中找到方法,就直接执行,不再搜索
- 如果没有找到,就查找下一个类中是否有对应的方法,如果找到,就直接执行,不再搜索
- 如果找到最后一个类,还没有找到方法,程序报错