Object-oriented Overview

写在前面

本文并不是非常专业的科普文章。只是笔者自己在学习过程中得到的一些经验和总结。为了方便日后的回顾与再思考,才想到了要用写下来的方式放在公众号上。大家可以在看完之后提出自己的思考与问题,也可以就文章中出现的一些错误向公众号反馈。看到之后我都会一一回复的~非常感谢大家的支持,如果大家也有和我一样的想法想要将自己在日常学习的一些总结记录下来的话,也欢迎大家加入!

今天我们将要来聊聊面向对象(object-oriented)编程范式。笔者第一次接触这个概念是在大一下的“软件工程与计算I”这门课上,老师用了大半学期试图让我们明白面向对象中的一些基本概念与思想,只能说目前为止自己还处在一个“门外汉”的阶段。不过今天还是就我一些学习之后的想法来简单谈谈面向对象

1 前言 – 编程范式的过去与现在

编程范式一词最早来自 Robert Floyd在1979年图灵奖的颁奖演说,是程序员看待程序应该具有的观点,代表了程序设计者认为程序应该如何被构建和执行的看法,与软件建模方式和架构风格有紧密关系。

上面一段话摘自知乎:《聊聊编程范式》。在我看来,编程范式其实就是程序员的思想所在。每一种编程语言都是死的,但编程背后是程序员对问题和目标的不断思考和探索。历史的滚滚长河也证明了一点,从最早杂乱无章的“面条式代码”到第一次出现“结构化编程”。再到如今十分流行也是本篇重点的“面向对象编程”,以及“函数式编程”。

编程范式就像是程序员的思维底座一样,决定了程序员在设计中所考虑的因素以及代码的结构。程序员把领域问题映射到某个编程范式上,然后通过编程语言来实现。下面我们就来简单回顾一下编程范式的历史。

1.1 结构化编程之前

这是编程最早出现的时候,程序员通过直接在硬件上的操作来实现一系列的目的,高级语言还没出现之前,程序员通过直接编写汇编语言或者机器指令来实现编写一个程序。

这个阶段的程序规模很小,一般也是杂乱无章的。归根结底是由于硬件发展的限制导致当前阶段还不是很需要规范清晰的结构来统一代码框架。

当时最出名的可能就是goto语句了,goto语句导致程序中代码的跳转毫无章法,一个程序的维护与修改极其的困难,后来goto语句就被大家认为是对开发程序十分有害,便被淹没在历史长河中了。

1.2 结构化编程

结构化编程的典型代表可以说非C语言莫属,C语言的出现让程序员不再像以前一样需要很经常的与硬件层面打交道,可以说降低了程序员编程的门槛,同时也提供了对计算机很好的抽象。结构化编程的中心思想可以用八个字来概括:“自顶向下,逐步求精”。

这八个字实际上就是将一个复杂的问题不断向下分解成一个个小模块,然后通过解决这些小模块再汇总起来解决最顶层的大问题。结构化编程可以说是最接近图灵模型(硬件系统)的一种编程范式了。它追求将数据结构与算法分离(程序 = 数据结构 + 算法),通过顺序、选择、分支三种流程结构的语句来实现想要的功能。

结构化编程的一个好处就是流程清晰了,从main函数开始可以十分清楚的了解程序的结构组成以及是如何实现功能的。但同时,结构化编程带来的问题就是随着程序规模的不断增大,结构化编程并不能够十分优秀的应对大规模程序中的领域问题。

结构化编程在抽象成我们现实世界所拥有的东西的方面还有欠缺,并不能够做到非常好的将现实世界的模型通过结构化编程直接映射到代码中。

软件规模的逐渐扩大带来的组织管理和抽象问题,让面向对象的编程范式应运而生。

1.3 面向对象编程

面向对象编程的出现很大一部分是为了解决大规模软件开发过程中的问题。面向对象的代表语言有C++Java等。面向对象的核心为以下三点:

  1. 封装
  2. 继承
  3. 多态

下面让我们来了解一下究竟什么是面向对象?

2 什么是面向对象?

面向对象的首要工作就是认识待解决问题所涉及的基本对象和他们间的相互关系。然后通过将这些对象映射到计算机中,实现计算机对现实问题的模拟,得到与应用问题结构对应(一致)的程序系统结构。

​ – 徐家富 《对象式程序设计语言》

首先让我们来谈谈:什么是对象?现实世界中存在的一切东西我们都可以将其看做对象。你天天玩的手机可以看成是一个对象,你的父母、朋友等等都可以看成是对象。简单来说就是万物皆对象Alan Kay总结了“纯粹”的面向对象的五大基本特征:

  1. 万物皆对象在编程中,你可以将对象想象成一种特殊的变量。它能够存储数据,也可以在你对他发送消息的时候执行他所拥有的行为。从面向对象的理论上看,在解决问题的过程中,我们首先需要从问题中抽象出许许多多个对象并在程序中将其表达出来。

  2. 程序是一组对象,通过消息传递来告知彼此应该做什么。要请求调用一个对象的方法(这里的方法就是C语言中的函数),你需要向该对象”发送消息“

  3. 每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。所以,尽管对象的概念非常简单,但在程序中却可达到任意高的复杂程度。

  4. 每个对象都有一种类型。根据语法,每个对象都是某个“类”的一个“实例”。其中,“类”(Class)是“类型”(Type)的同义词。一个类最重要的特征就是“能将什么消息发给它?”。

  5. 同一类所有对象都能接收相同的消息。这实际是别有含义的一种说法,大家不久便能理解。由于类型为“圆”(Circle)的一个对象也属于类型为“形状”(Shape)的一个对象,所以一个圆完全能接收发送给"形状”的消息。这意味着可让程序代码统一指挥“形状”,令其自动控制所有符合“形状”描述的对象,其中自然包括“圆”。这一特性称为对象的“可替换性”,是OOP最重要的概念之一。

Grady Booch 提供了对对象更简洁的描述:一个对象具有自己的状态,行为和标识。这意味着对象有自己的内部数据(提供状态)、方法 (产生行为),并彼此区分(每个对象在内存中都有唯一的地址)。

嗯。单纯的语言描述可能会让你感到有点懵,下面我们通过一个例子来简单的说一下什么是对象。我们将会构建一个简单的“人”对象,一个人他该具有哪些属性呢?这应该要看问题是从哪个方面来看待Human的,这里我们就不考虑这些复杂的因素了。

// 对人进行一个抽象来构建对象
class Human {
// 人都有心脏
Heart heart;
// 人的其他一些属性
...

// 人会吃饭
public void eat() {}
// 人会走路
public void walk() {}
...
}

上述就是简单的用Java语言构建出了“Human”这个对象。该对象抽象了我们每个人都应该有的数据和行为。

当然上述并不是说面向对象是为了简单的抽象出共性以防止代码重复,如果要防止代码重复建议使用组合。

知道了什么是对象之后,面向对象编程的思想就可以看成是一个个的对象相互发送消息的一个过程。面向对象将领域问题映射成实体加关系(领域 = 实体 + 关系),而不是数据结构 + 算法。

那什么是发送消息呢?其实就是两个对象之间的协同合作,有点类似于结构化编程中的调用函数。这个我们留到以后再讲,大家现在可以将发送消息看成是某个对象调用另一个对象的方法。

3 面向对象与结构化编程的区别

这里引用一个例子,该例子十分出色的说明了面向对象编程和结构化编程的区别。

问题描述:现在我们要将大象放到冰箱当中,需要几个步骤?

这个是大家比较熟悉的问题了,问题的答案也十分的清楚,需要三个步骤:

  1. 将冰箱门打开
  2. 将大象放进去
  3. 将冰箱关上

上述的这个答案呢,就是很典型的结构化编程的思想,我们思考的是过程,是“如何做”的问题。那如果我们用面向对象的思想来解答,答案又是如何呢?答案是这样的,可能略显滑稽:

  1. 冰箱,把门打开
  2. 大象,钻进冰箱
  3. 冰箱,把门关上

这就是面向对象思想解决这个问题的思路,我们关注的是“对象”,而不是过程,这里的冰箱和大象都被我们视作“对象”,并且冰箱有“开门”和“关门”两种行为,大象有“钻进冰箱”这种行为。然后通过互相发送消息解决了该问题。在面向对象中,我们思考的是“用什么做”,即这个问题涉及到了哪些对象。通过构建对象来解决问题,是面向对象的一个基本特征。

综上所述,结构化编程其实是对机器行为的一种说明,在汇编语句和机器指令中,机器所想的就是该如何做,而到了面向对象,程序员们注重的是对物理世界中对象的刻画,该如何将这个问题中的对象表达出来,是面向对象思想关心的问题。

小结

这篇文章带大家初步了解了编程范式的发展过程,让大家简单知道了面向对象的一些基本概念。下一篇文章会详细展开跟大家分享面向对象中核心的三个特征:

  1. 封装
  2. 继承
  3. 多态

感谢大家能够仔细的阅读完这篇文章,希望阅读完你能够有所收获。如果对文章内容有所疑问可以私戳公众号后台。感激不尽~

Reference

  1. 《On Java 8》
  2. 聊聊编程范式 - 知乎 (zhihu.com)
  3. 南京大学2020软件工程课程–软件工程与计算I
  4. 南京大学2021计算机科学与技术课程–Java高级程序设计
文章作者: ZY
文章链接: https://zyinnju.com/2022/02/13/Object-oriented-Overview/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ZY in NJU