欢迎来到面向对象编程(OOP)的世界!如果你已经成功掌握了类与对象的概念,那么你已经准备好迈出重要的一步:理解这些类之间是如何交互的。
可以将类想象成大型机器中不同组件的蓝图。本章将重点介绍如何连接这些组件的“线路与螺栓”,使它们能够作为一个统一的系统协同工作。掌握这些关系对于编写高效、灵活且强大的代码至关重要!
1. 理解类之间的关系:为什么要建立连接?
在现实世界的系统中,没有任何实体是完全孤立存在的。例如,银行账户需要客户,汽车需要引擎,球队需要球员。
面向对象编程(OOP)允许我们通过类之间的正式关系来建模这些现实世界的连接。你需要掌握的两种主要关系是继承(Inheritance)和关联(Association)。
小贴士:理解这些关系有助于你设计出更易于调试和更新的系统(这与软件开发中可维护性的概念息息相关)。
2. 继承:一种“是一个”(Is-A)的关系
什么是继承?
继承是一种基础关系,在这种关系中,一个类基于另一个类构建,并获取其属性和方法。它模拟的是一种“是一个”(Is-A)的关系。
例如:狗(Dog)是一种哺乳动物(Mammal)。汽车(Car)是一种交通工具(Vehicle)。
- 原始类称为基类(Base Class)(也称为父类或超类)。
- 新的专业化类称为子类(Subclass)(也称为派生类或子类)。
它的主要优势是什么?代码重用!如果所有动物都需要进食,你只需在基类(Animal)中定义一次 eat() 方法,所有的子类(Dog, Cat, Bird)就会自动继承它。
类比:交通工具蓝图
想象你有一份通用交通工具(Vehicle)(基类)的详细蓝图。这份蓝图包含了像 start_engine() 这样的方法,以及 colour(颜色)和 speed(速度)这样的属性。
当你创建汽车(Car)(子类)的蓝图时,你不需要重写所有内容。你只需声明:“汽车继承自交通工具”,然后添加只有汽车才具备的特定属性,例如 number_of_doors(车门数量)。
受保护的访问修饰符(折中方案)
在定义基类的属性或方法时,我们使用访问修饰符(如 public 或 private)来控制可见性(这是封装的一部分)。
受保护(Protected)访问修饰符(在图表中用 # 表示)在继承中非常特殊:
- 公有(Public,
+):被任何人访问。 - 私有(Private,
-):仅在定义它的类内部访问。 - 受保护(Protected,
#):在定义的基类以及所有子类内部可以访问,但不能被外部对象访问。
为什么要使用受保护访问?它允许子类管理或修改父类的核心功能,同时又避免了程序其他部分对其进行随意的篡改。
方法重写(Overriding)
有时,子类继承了一个方法,但该方法在子类中的执行方式需要与基类不同。这就是重写(Overriding)的用武之地。
重写是指在基类中定义的方法在子类中被重新定义(修改),从而使子类实例表现出不同的行为。
重写的步骤示例:
- 交通工具(Vehicle)(基类)有一个方法:
calculate_fuel_economy()。 - 电动汽车(ElectricCar)(子类)继承了这个方法。
- 由于电动汽车不使用汽油,子类重写了
calculate_fuel_economy(),改用计算能量消耗(例如:每公里耗电多少千瓦时)的方法。 - 当你对一个电动汽车对象调用此方法时,会使用子类版本的逻辑。
重点总结:继承
继承模拟的是“是一个”(Is-A)。它涉及一个基类和一个子类,支持专业化和代码重用。重写允许子类改变继承来的行为。受保护(#)修饰符仅允许基类及其子类访问相关成员。
3. 关联:一种“拥有一个”(Has-A)的关系
什么是关联?
关联是两个对象之间一种更广泛、更松散的关系,其中一个对象仅仅是使用或包含另一个对象。它模拟的是一种“拥有一个”(Has-A)的关系。
如果对象 A 使用对象 B,我们称对象 A 与对象 B 关联。
你知道吗?关联是一种比继承弱得多的关系。对象可以在没有与其关联的对象的情况下正常存在。
示例:足球模拟程序(根据教学大纲语境)
- 我们有一个球队(Team)类和一个球员(Player)类。
- 球队“是”一名球员吗?不是。
- 球队“拥有”球员吗?是的,一个球队对象包含或使用了多个球员对象。
每当对象需要交互或链接,但其中一个并不是另一个的特殊版本时,我们就会使用关联。
重点总结:关联
关联模拟的是“拥有一个”(Has-A)。它意味着一个对象使用了另一个对象。当对象是独立的实体但需要协作时使用(例如:一个客户拥有一个地址)。
4. 可视化关系:类图
为了清晰地传达类之间的链接方式,程序员使用图表(通常基于 UML —— 统一建模语言)。你需要熟悉继承和关联的符号表示,以及访问权限的标记方法。
访问权限符号
这些符号表示类框中属性和方法的可见性:
+:公有访问(Public)(任何人都可以访问)-:私有访问(Private)(只有类本身可以访问)#:受保护访问(Protected)(类及其子类可以访问)
类结构示例(在图表中)
类名
- 私有属性
# 受保护属性
+ 公有属性
- 私有方法()
+ 公有方法()
继承表示法(专业化)
继承用一条实线表示,末端有一个空心的封闭箭头,指向基类。
箭头指向父类:“子类依赖于父类的定义。”
子类 ▲ 基类
|
关联表示法(使用)
关联通过连接两个关联类的实线来表示。你可能会看到一个指示使用方向的箭头,如果关系是双向的,则没有箭头。
球队类 ------------------ 球员类
如果关系是单向的(例如:A 类使用 B 类,但 B 不知道 A 的存在),你会添加一个简单的开口箭头。
A 类 ------------------> B 类
快速回顾:关系符号
- 继承:空心三角箭头,指向上方(指向父类)。
- 关联:简单的实线或带开口箭头的线。
- 访问:
+(公有),-(私有),#(受保护)。
继续练习在图表中识别这些符号,并将其与专业化(继承)和协作(关联)这些 OOP 核心概念联系起来。你一定能行的!