面向对象编程思想入门指南

什么是面向对象?

面向对象编程(Object-Oriented Programming,简称 OOP)是一种通过“模拟现实世界事物”的方式设计和实现程序的思想。在 OOP 中,我们用“类”和“对象”来描述问题,把复杂的程序划分成一个个独立的模块。


1. 类和对象的关系

  • 是一个“模具”或“蓝图”,定义了事物的属性和行为 —— 对应着抽象。
  • 对象是类的具体实例,从模具中“造”出来的实际东西。

用一个文本绘图来形象表示:

类 (模具/蓝图):
+--------------------+
|      Car类         |
|--------------------|
| 属性:  brand       |
|        color       |
|--------------------|
| 行为:  drive()     |
+--------------------+

对象 (具体实例):
+--------------------+       +--------------------+
|   car1 对象        |       |   car2 对象        |
|--------------------|       |--------------------|
| brand: BMW         |       | brand: Audi        |
| color: red         |       | color: blue        |
|--------------------|       |--------------------|
| 行为: drive()      |       | 行为: drive()      |
+--------------------+       +--------------------+

详细解释

  • Car类 是一个模板,定义了所有汽车应该具备的属性(如 brandcolor)和行为(如 drive())。它不代表一辆实际的车,而是描述车的特征。所以,在现实生活中,没有办法拿出一个实际的"车”的东西,只能说某某东西是车,是一个抽象的概念
  • 对象car1car2Car类 的实例,具体的汽车对象。它们有自己的属性值(如 car1 是红色的宝马,car2 是蓝色的奥迪),并能执行 drive() 方法,这是一个具体的概念

2. 封装:保护数据,提供接口

封装是 OOP 的一个重要特性。它允许将对象的内部细节隐藏起来,仅通过公开的方法操作对象。

示意图

+------------------+
|   Car 类         |
|------------------|
| 属性:            |
| - brand (私有)   |
| - color (私有)   |
|------------------|
| 行为:            |
| + drive()        |
| + get_brand()    |
| + set_brand()    |
+------------------+

详细解释

  • 在这个示意图中,brandcolor 是私有的(用 - 表示),这意味着外部代码不能直接访问这些属性,只有通过 get_brand()set_brand() 等公开方法才能访问和修改它们。这样,封装保护了数据的完整性,并且提供了控制和安全性。
  • + 表示这些方法是公开的,可以被外部调用。通过封装,我们可以让对象控制自己的数据,防止不安全或不合法的操作。

3. 继承:在现有基础上扩展

继承允许一个类从另一个类“继承”属性和行为,减少代码重复。

示意图

父类: Vehicle
+------------------+
|   Vehicle 类     |
|------------------|
| 属性:            |
| - speed          |
|------------------|
| 行为:            |
| + move()         |
+------------------+

子类: Car
+------------------+
|   Car 类         |
|------------------|
| 继承自: Vehicle  |
|------------------|
| 新属性:          |
| - brand          |
| - color          |
|------------------|
| 新行为:          |
| + drive()        |
+------------------+

详细解释

  • Vehicle 类是父类,定义了所有交通工具共有的属性和行为,比如 speedmove()
  • Car 类是子类,它继承了 Vehicle 类的属性和方法,所以 Car 类可以直接使用 move() 方法。与此同时,Car 类还扩展了自己的属性(如 brandcolor)和方法(如 drive())。
  • 继承让代码复用成为可能,避免了重复编写相同代码。

4. 多态:同名行为,不同实现

多态指的是同一个方法在不同对象上可以有不同表现形式。例如,动物都有“叫”的行为,但不同动物的叫声不一样:

示意图

+------------------+       +------------------+
|   Dog 类         |       |   Cat 类         |
|------------------|       |------------------|
| 行为:            |       | 行为:            |
| + make_sound()   |       | + make_sound()   |
|    输出: 汪汪汪   |       |    输出: 喵喵喵   |
+------------------+       +------------------+

代码运行时:
dog = Dog()
dog.make_sound()  -> 输出: 汪汪汪

cat = Cat()
cat.make_sound()  -> 输出: 喵喵喵

详细解释

  • Dog 类和 Cat 类都有一个 make_sound() 方法,但它们的实现不同。Dogmake_sound() 输出 “汪汪汪”,而 Catmake_sound() 输出 “喵喵喵”。
  • 这就是多态的表现,同一个方法在不同的对象上执行时会有不同的行为。多态增加了程序的灵活性和扩展性。
  • 多态往往来自继承,Dog和Cat 相当于都继承自一种会发出声音的动物类

5. 结合例子:一个完整的面向对象设计

假设我们设计一个交通工具系统:

示意图

+--------------------+
|    Vehicle 类      |
|--------------------|
| 属性:              |
| - speed            |
|--------------------|
| 行为:              |
| + move()           |
+--------------------+
        ↑
        |
+--------------------+       +--------------------+
|      Car 类        |       |      Bike 类       |
|--------------------|       |--------------------|
| 属性:              |       | 属性:              |
| - brand            |       | - gear_count       |
| - color            |       |--------------------|
|--------------------|       | 行为:              |
| 行为:              |       | + pedal()          |
| + drive()          |       +--------------------+
+--------------------+

详细解释

  • Vehicle 类是基类,定义了交通工具的共同特性,如 speedmove() 方法。
  • CarBike 类分别继承了 Vehicle 类的属性和行为,同时又添加了自己特有的属性和方法,如 Carbrandcolor,以及 Bikegear_countpedal() 方法。
  • 这种设计使得程序结构更清晰、模块化,且易于扩展,比如增加新的交通工具只需新建一个继承自 Vehicle 的子类。

总结:为什么选择面向对象?

  1. 模块化管理:将代码分成小块,便于开发和维护。
  2. 复用性强:类可以反复使用,减少重复代码。
  3. 扩展性好:通过继承和多态,轻松添加新功能。

用通俗的话说,面向对象编程让程序像搭乐高积木一样简单,每个对象独立、灵活,最终组成一个强大的系统。

缺点和限制

面向对象编程(OOP)虽然有很多优点,但它也有一些缺点和局限性。面向对象编程提供了优秀的模块化和复用特性,但它也引入了复杂性、性能开销和不适合某些应用场景的问题。为了克服这些缺点,开发者需要在项目开始时仔细考虑是否使用 OOP,或者在需要时将 OOP 与其他编程范式(如函数式编程)结合使用。以下是一些主要的缺点:

1. 复杂性

  • 学习曲线陡峭:对于初学者来说,面向对象编程的概念,如类、对象、继承、封装和多态,可能比较难以理解,尤其是如何合理设计类的关系和结构。
  • 过度设计:为了符合面向对象的原则,开发者有时会进行过度设计,创建不必要的类和复杂的继承体系,使代码变得难以维护和扩展。

2. 性能开销

  • 内存消耗:对象比简单的数据结构占用更多内存,因为对象需要存储实例变量和方法等信息。
  • 运行效率:由于对象方法的调用需要经过额外的层次(如虚拟方法表、动态绑定等),在性能要求高的场合,这种开销可能不容忽视。

3. 不适合所有问题

  • 某些问题的非最佳解决方案:面向对象编程并不总是最好的方法。对于一些任务,尤其是那些计算密集型或数据驱动型的问题(如简单的数据处理或统计分析),过程式编程或函数式编程可能更为合适。
  • 复杂的业务逻辑:在一些需要复杂业务逻辑的系统中,OOP 可能会导致代码变得难以跟踪和理解,因为类和方法的层次结构可能过于复杂。

4. 代码重复

  • 继承导致的代码重复:虽然继承可以促进代码复用,但如果使用不当,会导致子类中重复代码的增多。例如,如果父类和子类之间的关系复杂,可能会导致难以维护的代码。
  • 子类的膨胀:如果一个类的继承树很深,子类会继承大量的属性和方法,可能会造成一些不必要的冗余和代码重复。

5. 过度使用继承

  • 耦合性增加:如果设计中过度使用继承,会使得不同类之间的关系变得复杂,导致紧密耦合,降低了代码的可维护性和扩展性。
  • “菱形继承”问题:在多重继承中,如果一个类继承自多个父类,可能会遇到菱形继承问题,这会导致不明确的属性和方法继承,从而增加了复杂性。

6. 设计和维护困难

  • 设计复杂:在构建一个大型的面向对象系统时,需要考虑类之间的关系和交互,这可能需要复杂的建模和设计工作。
  • 重构困难:如果系统的设计不够合理或类之间的依赖关系过于紧密,重构代码会变得困难,可能会影响到大量的代码片段。
  • 希望读者可以根据这篇文章,再去理解python的一些设计逻辑,同时后面我也会再分享一些C++的基础学习文章,有了面向对象的思想,学习起来会更轻松和通透
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾工

雁过留声

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值