Skip to content

类 —— 面向对象编程

27 / 44

面向对象编程

注意当前这一小节所论述的内容不是专属于哪个编程语言比如 Python、JavaScript 或者 Golang)。

面向对象编程Object Oriented Programming, OOP是一种编程的范式(Paradigm),或者说是一种方法论(Methodology)—— 可以说这是个很伟大的方法论在我看来现代软件工程能做那么复杂的宏伟项目基本上都得益于这个方法论的普及

争议

现在,OOP 的支持者与反对者在数量上肯定不是一个等级绝大多数人支持 OOP 这种编程范式

但是从另外一个角度反对 OOP 的人群中牛人比例更高 —— 这也是个看起来颇为吊诡的事实

比如,Erlang 的发明者Joe Armstrong 就很讨厌 OOP,觉得它效率低下他用的类比也确实令人忍俊不禁说得也挺准的

支持 OOP 的语言的问题在于它们总是随身携带着一堆并不明确的环境 —— 你明明只不过想要个香蕉可你所获得的是一个大猩猩手里拿着香蕉…… 以及那大猩猩身后的整个丛林
—— Coders at Work

创作 UTF-8 Golang 的程序员 Rob Pike更看不上 OOP, 2004 年的一个讨论帖里直接把 OOP 比作Roman numerals of computing” —— 讽刺它就是很土很低效的东西八年后又挖坟把一个 Java 教授写的 OOP 文章嘲弄了一番:“也不知道是什么脑子认为写 6 个新的 Class 比直接用 1 行表格搜索更好?”

[Paul Graham](https://en.wikipedia.org/wiki/Paul_Graham_(programmer) —— 就是那个著名的 Y-Combinator 的创始人 —— 也一样对 OOP 不以为然 Why Arc isn't Especially Object-Oriented 说他认为 OOP 之所以流行就是因为平庸程序员(Mediocre programers)太多大公司用这种编程范式去阻止那帮家伙让他们捅不出太大的娄子……

然而争议归争议应用归应用 —— 就好像英语的弊端不见得比其他语言少可就是最流行那怎么办呢用呗 —— 虽然该抱怨的时候也得抱怨抱怨

从另外一个角度望过去大牛们如此评价 OOP 也是很容易理解的 —— 因为他们太聪明又因为他们太懒得花时间去理解或容忍笨蛋…… 我们不一样最不一样的地方在于我们不仅更多容忍他人而且更能够容忍自己的愚笨所以视角就不同了仅此而已

并且上面两位大牛写的编程语言现在也挺流行,Joe Armstrong Erlang Rob Pike Golang,弄不好早晚你也得去学学去用用……

基本术语

面向对象编程(OOP),是使用对象(Objects)作为核心的编程方式进而就可以把对象(Objects)的数据和运算过程封装(Encapsulate)在内部而外部仅能根据事先设计好的界面(Interface)与之沟通

比如你可以把灯泡想象成一个对象使用灯泡的人只需要与开关这个界面(Interface)打交道而不必关心灯泡内部的设计和原理 —— 说实话这是个很伟大的设计思想

生活中我们会遇到无数有意无意应用了这种设计思想的产品 —— 并不仅限于编程领域你去买个车回来它也一样是各种封装之后的对象当你转动方向盘操作界面的时候你并不需要关心汽车设计者是如何做到把那个方向盘和车轮车轴联系在一起并如你所愿去转向的你只需要知道的是逆时针转动方向盘是左转而顺时针转动方向盘是右转 —— 这就可以了

在程序设计过程中我们常常需要对标现实世界创造对象这时候我们用的最直接手段就是抽象(Abstract)。抽象这个手段在现实中漫画家们最常用为什么你看到下面的图片觉得它们俩看起来像是人尤其是在你明明知道那肯定不是人的情况下却已然接受那是两个漫画小人的形象

这种描绘方式就是抽象很多没必要的细节都被去掉了或者反过来说没有被采用),留下的两个特征一个是头一个是双眼 —— 连那双眼睛都抽象到只剩下一个黑点了……

这种被保留下来的必要的特征”,叫做对象的属性(Attributes),进而这些抽象的对象既然是的映射它们实际上也能做一些抽象过后被保留下来的必要的行为”,比如说话哭笑这些叫做对象的方法(Methods)。

从用编程语言创造对象的角度去看所谓的界面就由这两样东西构成

  • 属性 —— 用自然语言描述通常是名词(Nouns)
  • 方法 —— 用自然语言描述通常是动词(Verbs)

从另外一个方面来看在设计复杂对象的时候抽象到极致是一种必要

我们为生物分类就是一层又一层地抽象的过程当我们使用生物这个词的时候它并不是某一个特定的我们能够指称的东西…… 然后我们开始给它分类……

所以当我们在程序里创建对象的时候做法常常是

  • 先创建最抽象的(Class)
  • 然后再创建子类(Subclass)……

它们之间是从属关系是

Class ⊃ Subclass

OOP 这叫继承(Inheritance)关系比如狗这个对象就可以是从哺乳动物这个对象继承过来的如果哺乳动物有这个属性(Attributes),那么在狗这个对象中就没必要再重新定义这个属性了因为既然狗是从哺乳动物继承过来的那么它就拥有哺乳动物的所有属性……

每当我们创建好一个类之后我们就可以根据它创建它的许多个实例(Instances)。比如创建好了这个类之后我们就可以根据这个类创建很多条狗…… 这好多条狗就是狗这个类的实例

现在能把这些术语全部关联起来了吗

  • 对象封装抽象
  • 界面属性方法
  • 继承子类实例

这些就是关于面向对象编程方法论的最基本的术语 —— 无论在哪种编程语言里你都会频繁地遇到它们

对象这两个词给人的感觉是经常被通用 —— 习惯了还好但对有些初学者来说就感觉那是生命不能承受之重。—— 这次不是英文翻译中文时出现的问题在英文世界里这些词的互通使用和滥用也使相当一部分人我怀疑是大部分人最终掌握不了 OOP 这个方法论

细微的差异在于视角的不同

之前提到函数的时候我用的说辞是

  • 你写了一个函数而后你要为这个产品的使用者写说明书……
  • —— 当然产品使用者之中也包括未来的你……

(Class)这个东西也一样它也有创作者和使用者

你可以这样分步理解

  • 你创造了一个类(Class),这时候你是创作者从你眼里望过去那就是个类(Class);
  • 而后你根据这个类的定义创建了很多实例(Instances);
  • 接下来一旦你开始使用这些实例的时候你就成了使用者从使用者角度望过去手里正在操作的就是各种对象(Objects)……

最后补充一下不要误以为所有的 Classes 都是对事物名词的映射 —— 虽然大多数情况下确实如此

对基本概念有了一定的了解之后再去看 Python 语言是如何实现的就感觉没那么难了