Python学习笔记12:进阶篇(二),类的继承与组合

类的继承

我们在编写一系列的类的时候,会发现这些类很相似,但是又有各自的特点和行为。在编写这些类的时候,我们可以把相同的部分抽象成一个基类,然后根据其他不同的特点和行为,抽象出子类,继承这个基类。通过继承,我们就可以方便的完整这一些列类的抽象。

示例

python 复制代码
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.country = "中国"  # 设置默认值

    def speak(self):
        print(f"大家好, 我的名字是{self.name}, 今年{self.age}岁,我来自{self.country}. 我讲的是普通话.")


class GuangdongPerson(Person):

    def __init__(self, name, age):
        super().__init__(name, age)
        self.province = "广东"

    def speak(self):
        print(f"大家好, 我是{self.name}, 今年{self.age}岁,我来自{self.country}{self.province}. 我会讲广东话.")


class TaiwanPerson(Person):

    def __init__(self, name, age):
        super().__init__(name, age)
        self.province = "台湾"

    def speak(self):
        print(f"大家好, 我是{self.name}, 今年{self.age}岁,我来自{self.country}{self.province}. 我会讲台湾话.")


zhang_san = GuangdongPerson("张三", 18)
li_si = TaiwanPerson("李四", 20)
zhang_san.speak()
li_si.speak()

例子不能说讲的很好哈,能理解就行。像我之前推荐的书,书里的举例是car,其他教程里面可能还有shape。但是举什么例子不重要,重要的是了解什么是继承,继承能干什么,有什么意义,好处和坏处是什么。

什么是继承

继承是一种面向对象编程的基本特性,它允许我们定义一个类(称为子类或派生类),该类可以从另一个已经存在的类(称为父类或基类)那里继承属性和方法。这意味着子类会自动获得父类的所有功能,同时还可以定义或修改自己的属性和方法,或者覆盖父类的方法来实现特定的功能。

在示例中,我们先定义了一个父类Person。而后定义了GuangdongPerson和TaiwanPerson两个类,这两个类定义了自己的属性,继承Person类的三个属性和函数,最后我们重写来自于父类的方法。

为什么要继承

继承的主要目的是促进代码的复用性、模块化和易于维护。通过继承,我们可以创建一个通用的基类来封装共同的行为,然后为具有特殊需求的子类添加或修改功能,而不需要重复编写相同的代码。

继承有哪些缺点

没有完美无缺的事物,继承在提供便利的同时也带来一些问题:

  1. 过度耦合: 如果子类过于依赖父类的实现细节,当父类发生变化时,可能会对子类产生意想不到的影响。这种紧密的耦合关系使得代码难以修改和维护。
  2. 复杂度增加: 随着继承层次的加深,类结构会变得更加复杂。开发者需要跟踪多个层级的继承关系,理解每个类的功能和责任变得困难。
  3. 灵活性降低: 继承是静态的,一旦一个类继承了另一个类,这种关系就固定下来,不能在运行时改变。这限制了代码的灵活性和可重用性。
  4. 菱形问题(Diamond Problem): 在多继承的语言中,如果多个父类拥有同一个方法或属性,子类可能会遇到冲突,不确定应该使用哪一个父类的实现。
  5. 代码可读性和可维护性下降: 过度使用继承可能导致"类爆炸",即类的数量急剧增加,这会使代码库变得庞大且难以管理。

什么时候用继承

选择使用继承主要取决于以下几个场景和原则:

  1. 共享行为和属性: 当多个类具有相似的属性和行为时,可以考虑使用继承。一个基类可以定义这些共性部分,而子类则专注于差异化的部分。例如,各种动物类可能都共享"移动"和"吃"的行为,但具体实现各不相同。
  2. 代码复用: 继承允许子类重用父类的代码,减少重复代码,提高代码的可维护性。如果多个类需要执行相同的操作或拥有相同的属性,通过继承可以避免重复定义这些内容。
  3. 层次结构: 当类之间存在明显的层次或分类关系时,继承是自然的选择。例如,在一个图形界面库中,Widget类可以作为基类,而Button、TextBox等具体控件类继承自它,形成一个清晰的层次结构。
  4. 接口一致性: 如果希望一组类提供一致的接口给外部使用者,即使它们的内部实现不同,也可以通过继承来实现。这使得客户端代码可以以统一的方式处理这些类的实例。
  5. 抽象类和接口: 使用抽象基类(ABC)可以定义一个接口或模板,强制子类必须实现特定的方法,从而保证了设计的一致性和约束性。

通常继承和组合两个方式来实现某些属性和行为的复用。当两个类之间的关系不是"is-a"的关系,而是"has-a"的关系时,组合(包含另一个类的实例)通常是更好的选择。

组合

当我们需要复用某些类的属性和行为的时候,使用继承的方式和客观事实相违背,但是有另一个符合客观事实的复用方式,就是组合。简单理解为定义一个类A的时候,将另一个已存在的类BA自己本身的一些属性和行为 放到一起组合成类A

什么是组合

组合(Composition)是面向对象编程中的另一种重要的设计原则,用于表示"整体-部分"(has-a)的关系,而不是继承所表达的"是一个"(is-a)的关系。在组合中,一个类的对象可以包含另一个或多个类的对象作为其属性,以此来实现更复杂的功能或结构,而无需通过继承来扩展类的功能。

组合的好处

  1. 灵活性:相比于继承,组合提供了更高的灵活性。因为对象可以在运行时动态地添加、替换或移除其组成部分,这使得系统更加灵活,更容易适应变化。
  2. 明确的责任分配:每个对象负责自身的功能,整体对象通过协调其组成部分来完成更复杂的任务,这有助于遵循单一职责原则。
  3. 避免继承的局限性:组合可以有效避免继承的缺点,如多重继承的菱形问题、过深的继承层次导致的复杂性等。
  4. 促进代码重用:通过将复杂对象构建为简单对象的组合,可以在不同的上下文中重用这些简单对象,而不需要创建新的继承层次。

什么时候用组合

  1. 当一个类需要使用另一个类的功能,但两者之间不存在"是一种"关系时。
  2. 当需要在运行时动态地调整或扩展对象的功能时。
  3. 当想要设计出高度可配置和可变的对象结构时。

示例

python 复制代码
class Engine:
    def start(self):
        print("Engine started.")


class ElectricEngine(Engine):
    def start(self):
        print("Electric Engine started.")


class InternalCombustionEngine(Engine):
    def start(self):
        print("Internal Combustion Engine started.")


class Car:
    def __init__(self):
        self.engine = Engine()  # Car类包含了一个Engine对象,这就是组合

    def set_engine(self, engine):
        self.engine = engine

    def start_car(self):
        self.engine.start()  # 通过组合的Engine对象来启动汽车


my_car = Car()
# 普通引擎
my_car.start_car()
my_car.set_engine(ElectricEngine())
# 电动引擎
my_car.start_car()
my_car.set_engine(InternalCombustionEngine())
# 汽油引擎
my_car.start_car()

在例子中,我们需要定义一个汽车类。汽车可以通过引擎启动。所以我们先定义一个引擎类来启动汽车。这个时候问题来了,汽车继承引擎,是不是很奇怪。汽车和引擎很明显不是is-a的关系,而是has-a的关系,所以我们需要使用组合的方式,将引擎类作为汽车的一个属性封装到汽车类中。

最后,使用不同的引擎,启动方法的实现也不一样,成功完成目标需求。

作业:

  1. 了解is-a和has-a,举出例子,分别使用继承和组合的方式实现类的复用。

下课!!!

点赞收藏关注,感谢支持!!!

相关推荐
databook12 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar13 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805113 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_13 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机20 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机21 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机21 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机21 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i21 小时前
drf初步梳理
python·django
每日AI新事件21 小时前
python的异步函数
python