谁说C语言不能面向对象(之一,前言)

    看到题目,我相信一定有很多人觉得,嗯,我确确实实是个逗比。各种权威资料上写得非常清楚,C语言是面向过程的语言,C++,Java,OC,Python,JS等这些才是面向对象的语言。这个逗比,竟然觉得C可以面向对象,看来他真的是个逗比。

    所以我在此先声明一下我起这个标题,以及,写这个系列文章的初衷。我并不是挑战权威,说C是面向对象的语言。确实,C的确是面向过程的语言,其中并没有包括任何面向对象的语法。而我通过这系列连载的文章,是想表达一个观点,所谓的“面向对象”或是“面向过程”,其实指的是一种编程思路,而任何程序语言都只是个编程的工具而已。只不过,在当初设计C语言的时候,并没有打算让C支持面向对象的语法,因此,C语言可能更加适合去编写一些面向过程的程序项目。但是,这并不代表,使用C语言就不能够面向对象编程。

    所以,面向过程是C的天赋,与之相对比较经典的就是Java,它天生面向对象。那么,我为什么非要让C语言去做一些它不擅长的事情呢?原因很简单,因为我在工作和生活中,遇到了非常多虽然使用了面向对象的程序设计语言,但是,却根本没有好好利用面向对象的特性,写出来的代码,仍然是面向过程的,仅仅是把面向对象的语言作为一种语法扩充,而并没有做到面向对象。因此,我写这系列的文章,用一个大多数人认为它只能面向过程的语言——C语言来做一个反差对比,向大家诠释,就连C这样面向过程的语言,都能够做到很优雅的面向对象,并且,使用了面向对象以后,优势又非常明显。那么,当我们再使用本身就支持面向对象的语言的时候,如果再不能够充分利用面向对象的特性,那真的是所谓暴殄天物了。

    在我个人看来,程序代码,不仅仅是一个工具、一种工程方式、一种与计算机交流的方法而已。代码更是一种艺术品,是和同行之间交流、表达设计与实现的美的体现。好的代码就如同一篇诗情画意的散文,能让阅读的人感受到作者在书写时的环境和心情,能够让人感受到清晰的思路表达。而耦合性高、可读性差的代码,就好似没有经过排版的草稿纸,虽然结果是正确的,但是过程、思路是一片混乱的,没有美感。如果你觉得把代码当做艺术品这个境界太高不容易接受的话,那我不妨换一个角度来解释。如果给你一篇文章,让你从这篇文章中找出一些关键的、有用的信息,与此同时再看看文章中有没有出现什么错误,帮助作者来改正。这种时候,如果这篇文章字迹清晰、表达清楚、情节优美,那我想,你一定愿意去细细品味,仔细阅读,也很容易从中找到需要的关键点,如果其中有什么错误,也会变得比较明显,容易改正。可是如果你拿到的是一篇字迹潦草,逻辑混乱,前言不搭后语的文章,那我想,你很难从中找到关键信息,而找到错误也会变得更难。

    对于我们的代码来说,也是同样的,我们很少会出现一个工程项目仅仅运行一次就再也不需要运行的情况。代码总是需要维护的,也许是添加新的特性,也许是去消除bug打补丁,而这些维护工作,有可能是代码的创造者来完成的,也可能是其他人来完成的。但不管是谁,要想维护代码,首先,他就需要读懂代码,然后,根据程序的现象去定位问题,找到管理这个部分的相关代码,分析后进行修改,然后还有测试验证。如果,代码维护人员拿到的是乱成一锅粥的代码,那这个维护成本可想而知。连读懂代码可能够不容易做到,那更别说修改了。

    因此,编写清晰、整洁的代码,不仅是个人的品德修养,更是项目维护的需要,于人于己都至关重要。

    那么,整洁的代码与面向对象又有什么关系呢?在我的理解,所谓整洁代码,讲究一个高内聚、低耦合。通俗来讲就是,模块的可拆分性,在模块内部的流程都是与这个模块强相关的,而单独的模块拿出来是可以独立运行的,模块间可以重新拼接组合。举个简单的例子来说,假如我要执行“买汉堡”这个操作,下面有两种写法,我们可以对比一下:

写法1:
1.从椅子上站起来
2.迈左脚
3.迈右脚
4.如果到未到达门口则返回2
5.弯腰
6.拿起左鞋子穿在左脚上
7.拿起右鞋子穿在右脚上
8.直起身
9.开门
10.出门
11.关门
12.迈左脚
13.迈右脚
14.如果未到达转交则返回12
15.转向正确的方向
16.如果未到达汉堡店则返回12
17.问服务员有没有汉堡,如果没有,程序结束
18.付款
19.等待
20.如果汉堡没有做好则返回19
21.拿到汉堡
22.程序结束
写法2:
1.出门
2.步行至汉堡店
3.购买汉堡

出门:
1.起身
2.走向门口
3.换鞋
4.出门

走路:
1.迈左脚
2.迈右脚
3.如果未到达目的地则返回1

换鞋:
1.拿起左鞋子穿在左脚上
2.拿起右鞋子穿在右脚上

步行至某地:
1.走路
2.如果未遇到转弯则返回1
3.如果未到达目的地则返回1

购买汉堡:
1.询问服务员是否有汉堡,如果没有则程序结束
2.付款
3.等待汉堡做好
4.拿到汉堡

等待某商品:
1.等待
2.如果该商品未准备就绪则返回1
3.拿到商品

    这两种写法中,很显然,第二种写法就更为整洁,首先,我们在“购买汉堡”这个过程中,看到的步骤是很清晰的,我只要先出门,走到汉堡店,然后买汉堡这样就可以了,而具体怎么出门,怎么走,怎么买,这些细枝末节的事情应该在更细化的分支中去明确,而不像写法1那样,所有的细节全部都混在一起,而对于关键的步骤以及整体的划分就很难读得出来。

    另一方面,就是模块的可重用性,如果按照写法1这样,我想再写一个买薯条的,或者买书包的程序,那买汉堡的程序就和它完全没有关系,所有的步骤都得重新去设计和编写。但是,如果是写法2的这样,这些模块就可以拿出来重新组合,像是出门、换鞋、走路这些过程是完全不需要变化的,而步行、购买这些过程,也仅仅是目的地和商品变了而已,我只需要修改参数即可,程序过程完全不需要改变。因此,这样做,不仅提升了代码可读性,还提升了代码重用性。

    当然,我相信,一定会有反对的声音说,这样做降低了性能。那么我希望大家思考一个问题,如果说,因为增加了调用过程而产生的额外开销,这件事情比代码可读性和重构性还重要,为什么又会诞生这么多新的程序语言?那我们直接用汇编写程序不就好了吗?随着计算机的不断发展,软硬件的不断进步,这种函数出入栈的开销,已经可以忽略不计了。相比而言,优化算法才是能够真正增加效率降低运行时间的方式。软件越来越复杂,如果我们还是用着汇编在写程序,我相信不会有现在所谓的AR和AI这些技术的诞生,程序员就会把几乎所有的时间用在怎么给硬件打交道上,而没有时间再去用软件创造新的东西。另外一方面就是我之前说过的维护成本。如果代码的维护性很差,那么,我们在这个基础上进行的修改就会有跟高的概率不能解决问题,甚至引入新的问题,而程序本身又是很脆弱的,很容易就会造成程序崩溃无法运行。与这种风险相比,那些所谓的“额外开销”,我想,应该就不再算什么了。

    回到之前的话题,既然整洁代码这么重要,那么,我们如何编写整洁的代码呢?业界有很多方法,关于如何编写程序可以更容易做到高内聚、低耦合,增强代码的可读性和可维护性。这些我们称为“设计模式”,而这些设计模式最基础的思路,就是面向对象(Object Oriented,以后简称OO),这就是整洁代码与OO之间的关系。

    因此,之后我会持续连载此系列文章,以C语言为例,来带领大家体验OO之美。

【本系列文章归逗比老师全权拥有,允许转载,但请务必在开头标注转载字样以及转载源连接。】

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

borehole打洞哥

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值