实现 Python | 继承关系

面向对象与继承面向对象思想有三大要素:

  1. 继承
  2. 封装
  3. 多态
面向对象编程(OOP)语言的一个重要功能就是 “继承”:
  • 它可以使用现有类的所有功能,并在无需重新编写原来类的情况下,对这些功能进行扩展
  • 通过继承创建的新类被称为 “子类” 或 “派生类”,被继承的类被称为 “基类”、“父类” 或 “超类”
  • 在 Python/ target=_blank class=infotextkey>Python 中,同时支持单继承与多继承
继承的概念举个例子,我们现在像创建猪、狗和猫三个类,它们都有名字和年龄属性,也都有一个叫的方法 。不同的是,猪有吃的方法、狗有看家的方法、猫有抓老鼠的方法 。按照之前的学习,我们会将代码写成这样:
class Pig:def __init__(self, name, age):self.name = nameself.age = agedef bark(self):print('叫')def eat(self):print('吃')class Dog:def __init__(self, name, age):self.name = nameself.age = agedef bark(self):print('叫')def guarding(self):print('看家')class Cat:def __init__(self, name, age):self.name = nameself.age = agedef bark(self):print('叫')def catch(self):print('抓老鼠')我们发现,虽然实现了需求,但是我们看到,这里面出现了大量的重复代码 。如果我们能将这些重复代码封装起来,比如封装到一个动物类中,然后猪、狗和猫分别都继承这个动物类,就可以让代码更加简洁 。
具体的实现方法为:
class Animal:def __init__(self, name, age):self.name = nameself.age = agedef bark(self):print('叫')class Pig(Animal):def eat(self):print('吃')class Dog(Animal):def guarding(self):print('看家')class Cat(Animal):def catch(self):print('抓老鼠')mimi = Cat('咪咪', 3)print(mimi.name, mimi.age)mimi.bark()mimi.catch()输出的结果为:
咪咪 3叫抓老鼠实现继承之后,子类将继承父类的属性和方法 。
不难看出,继承关系的特点为:
  • 增加了类的耦合性(耦合性不宜多,宜精)
  • 减少了重复代码
  • 使得代码更加规范化,合理化
组合与继承的对比:
  • 组合
  • 组合是指在新类里面创建原有类的对象,重复利用已有类的功能,是 has-a 的关系(如:猫有腿)
  • 原来类的对象作为整体,以新类的属性的形式存在
  • 继承
  • 继承允许设计人员根据其他类的实现来定义一个类的实现,是 is-a 的关系(如:猫是动物)
  • 子类可以直接使用父类中的属性和方法,就好像父类的属性和方法已经存在于子类中了一样
Python 3 中使用的都是新式类,如果一个类谁都不继承,那么它默认继承 object 类 。
继承虽然很好用,但是不能滥用,像之前说的,耦合程度不宜过高,否则逻辑会十分混乱:
  • 不要轻易地使用继承,除非两个类之间是 is-a 关系
  • 不要单纯地为了实现代码的重用而使用继承,因为过多的继承会破坏代码的可维护性,当父类被修改的时候,会影响到所有继承自它的子类,从而增加程序的维护难度与成本
  • 总结起来就是:组装的时候使用组合,扩展的时候使用继承
回到我们刚才的例子,猪、狗、猫三各类都只有动物一个父类,这种只有一个父类的继承方式,我们称作为单继承 。在单继承中,子类可以继承父类的属性和方法,修改父类,所有子类都会受到影响 。
isinstance和issubclassisinstance:
  • 用于检查实例类型
  • isinstance(对象, 类),用来判断对象是不是该类的实例对象
issubclass:
  • 用于检查类继承
  • issubclass(类1, 类2),用来判断类 1 是否是类 2 的子类
类与数据类型Python 与其他编程语言不同,当我们定义一个 class 的时候,我们实际上就定义了一个数据类型 。我们定义的数据类型和 Python 自带的数据类型,比如 str、list、dict 没什么两样:
print(isinstance(10, int))输出的结果为: True重写父类方法如果父类中的方法在子类中不适用,我们可以对其进行重写:
class Animal:def __init__(self, name, age):self.name = nameself.age = agedef bark(self):print('叫')class Dog(Animal):def bark(self):# 重写叫的方法print('汪汪汪!')def guarding(self):print('看家')wangwang = Dog('汪汪', 3)print(wangwang.name)wangwang.bark()


推荐阅读