《面向对象是怎样工作的》读书笔记

最近阅读了《面向对象是怎样工作的》这本书,感觉还不错,记录一下。

<!--more-->

1. OOP历史

预测未来最好的方法就是创造它。 ———— 艾伦·凯(Alan Kay),最早提出面向对象概念的人

面向对象的英文是 Object Oriented,直译为“以对象为中心”。

下面简述一下OOP出现的历史:

  1. 计算机只可以解释用二进制数编写的机器语言,为了让计算机执行预期的工作,最终必须有使用机器语言编写的命令群

  2. 为了改善这种低效的编程,汇编语言就应运而生了,汇编语言将无含义的机器语言用人类容易理解的符号表示出来

  3. 随后,用更贴近人类的表达形式来编写程序的高级语言被发明出来,从面向计算机转变成面向开发者

  4. 软件需求越来越复杂,提出了结构化编程,提倡只使用循序、选择和重复这三种结构来表达逻辑,同时废弃 Goto

  5. 为了方便维护程序,需要提高子程序的独立性,减少全局变量,一种是使用局部变量,一种是按值传递;出现了以结构化为基础的结构化编程语言,如C

  6. 结构化语言未解决的问题是:全局变量与可重复性差;OOP 打破了这个限制

目前市面上的教程存在的问题

  • 术语洪流,各种各样的概念术语
  • 比喻滥用,通过比喻来说明某些具体结构,猫叫狗叫动物叫
  • "一切都是对象"综合征,面向对象的技术范围很广

2. 三大基本概念

如果用一句话来概括面向对象,那就是“能够轻松地进行较难的软件开发的综合技术”,面向对象包含三个基础概念

  • 类,类Class是面向对象的最基本的结构,与其对应的概念是实例Instance,在大部分书籍中把这里叫做了“封装”,作者认为“类”更能表达其含义
  • 继承,系统地整理物的种类的共同点和不同点的结构
  • 多态,让向相似的类发送消息的方法通用的结构

类、多态和继承应该被明确定义为能提高软件的可维护性和可重用性的结构,在实际开发中,应按照编程结构来理解,而不是硬套现实世界

  • OOP 具有不使用全局变量的结构。

  • OOP 具有除公用子程序之外的可重用结构。

类结构将紧密关联的子程序(函数)和全局变量汇总在一起,创建大粒度的软件构件。通过该结构,我们能够将之前分散的子程序和变量加以整理。

多态和继承能够将公用子程序无法很好地处理的重复代码进行整合,彻底消除源代码的冗余

2.1. 类:封装

<类的功能之一:汇总>

能够将紧密联系的(多个)子程序和(多个)全局变量汇总到一个类中。优点如下。

  • 构件的数量会减少
  • 方法(子程序)的命名变得轻松
  • 方法(子程序)变得容易查找

<类的功能之二:隐藏>

能对其他类隐藏类中定义的变量和方法(子程序)。

这样一来,我们在写程序时就可以不使用全局变量了。实例变量融合了局部变量能够将影响范围局部化的优点以及全局变量存在期间长的优点。我们可以将实例变量理解为存在期间长的局部变量或者限定访问范围的全局变量。

<类的功能之三:创建很多个>

一旦定义了类,在运行时就可以由此创建很多个实例。

这样一来,即使同时处理文件、字符串和顾客信息等多个同类信息,也可以简单地实现该类内部的逻辑。

<OOP 的三大要素之一:类>

类是“汇总”“隐藏”和“创建很多个”的结构。

  • “ 汇总”子程序和变量。

  • “ 隐藏”只在类内部使用的变量和子程序。

  • 从一个类“创建很多个”实例。

2.2. 多态

<OOP 的三大要素之二:多态>

多态是统一调用子程序端的逻辑的结构,即创建公用主程序的结构。

多态可以说是创建公用主程序的结构。公用主程序将被调用端的逻辑汇总为一个逻辑,而多态则相反,它统一调用端的逻辑

在 OOP 出现之前,公用子程序就已经存在了,但公用主程序并没有出现。框架和类库等大型可重用构件群也正是因为多态的存在才成为可能

2.3. 继承

<OOP 的三大要素之三:继承>

继承是将类定义的共同部分汇总到另外一个类中,并去除重复代码的结构。

在 OOP 之前的由子程序构成软件的编程环境中,我们会创建一个公用子程序来汇总重复的命令群。同理,在由类构成软件的 OOP 环境中,我们可以创建一个公用类来汇总变量和方法。

3. OOP在内存中

在汇编语言占据主流的时代,这种最基本的知识就是硬件寄存器的结构,

在 C 语言时代则是指针结构。

而在编程语言进一步进化的今天,笔者认为最基本的知识则是“理解内存的使用方法”。这也可以说是使用 OOP 的程序员的基本素养。

线程的意思是“程序的运行单位”。英文单词“thread”是“线”的意思,进一步延伸出“生命线”“寿命”的含义,而“生命线”这一含义就能很贴切地表现计算机处理的运行单位。

进程表示的单位比线程大,一个进程可以包含多个线程。实际上,许多应用程序都是使用多个线程实现的

单个CPU在某个时刻只能处理一个线程,当 CPU 执行线程的处理时,并不是将一个线程从开始一直执行到结束,而是仅在非常短的规定时间(通常以毫秒为单位)内执行。在执行完这段规定时间后,即使该线程的处理还未完成,计算机也会暂时中断处理,转而处理下一个线程。

能够同时运行多个线程的环境称为多线程环境,通过并发处理多个线程,可以高效利用 CPU 资源。

三种内存区域

对于面向对象的语言而言,

  • 类信息位于静态区,主要保存类的基本信息,以及类的方法,同时内部使用一个虚函数表维持对于每个方法的引用

  • 在程序运行时,动态实例化的对象位于堆区,每个对象拥有自己独立的变量内存,但使用静态区公共的类方法

  • 而实际的变量位于栈区,通过指针维持对于堆区对象的引用

4. 使用OOP复用技术

OOP 带来的两种可重用技术。

一种是软件本身的重用,即准备通用性高的软件构件群进行重用,诸如类库、框架和组件等都属于这种技术

另一种是思想或技术窍门的重用,即对软件开发或维护时频繁出现的固定手法进行命名,形成模式,以供更多人重用,如设计模式

4.1. 类库

OOP在类库中的作用

基本的处理由框架端提供,应用程序特有的处理则利用多态进行调用。好莱坞原则一词可以用来表示这种框架结构的特征

如果这种框架完全适用,那么我们就可以轻松地创建复杂的应用程序。基本的使用方法就是继承框架提供的默认类(或者接口),并编写一些方法

4.2. 设计模式

设计模式是前人为了创建便于功能扩展和重用的软件而研究出的技术窍门集。具体来说,就是不依赖于编程语言和应用程序的应用领域,对在各种情况下反复出现的类结构进行命名,形成模式

软件设计目标:将易于维护和重用的软件结构的目标汇总为如下三点。

  • 去除重复

  • 提高构件的独立性

  • 避免依赖关系发生循环

5. UML

UML这三个字母的全称是Unified Modeling Language,直接翻译就是统一建模语言,简单地说就是一种有特殊用途的语言。

UML可帮助我们做软件需求分析和软件设计的工作,在OOP中,主要帮助分析系统流程、各个类的设计、依赖、组合和聚合等关系。

学习可以参考:最全面的UML教程

6. 小结

这本书从一个不太一样的角度来解释了面向对象的三个概念在软件开发中的具体作用,还是挺有收获的。