在我的工作和生活过程中,我曾经不止一次的被人问到,“什么是面向对象?什么是面向对象编程?”,而后来,我也像他们一样去问其他人同样的问题,可是,他们回答的结果和我当初的相仿一样让人吃惊!我大多可得到如下描述“把一类事物抽象成一个类,这就叫做面向对象编程。”也许,这是很多的初学者毫不犹豫的答案。然而,我并不想反驳你的观点,但如果我问你“面向对象和面向过程有什么异同”,也许,会有不少人回答诸如结构体和类之类异同的研究结果。
然而,事情的真相总是让人吃惊的,假设你在C++语言中使用结构体,你会发现他们几乎和类的结构至少在使用上是完全相同的!也许,终于会有人提出反驳的意见“结构体不能继承,而类是可以继承的!”那么,恭喜你,我们终于回到问题的点子上来了,虽然答案仍然是错误的,(C++中的结构体和类唯一的差别是默认访问的不同,类是私有,结构体是公有,仅此而已)但至少在一定程度上,你对面向对象是有所了解了。
虽然对于什么是面向对象编程一直是一个很有争议的话题,但我还是想尽量去描述它的本质。
曾经在我的学习和工作的过程中,我碰到过一些人,他们告诉我:“我使用了纯面向对象语言C#或是JAVA,那么当然,我的程序肯定是面向对象的。”然而,同样的,事实的真相总是那么让人不舒服,即使你使用了完全面向对象的语言,你所写的程序,也不一定能称为面向对象编程,大多时候,你的程序最多只能称为基于对象编程而已。
其实,对于这个结果你不必惊讶,很多有经验的程序员同样会告诉你相同的结果,
事实上,要搞清楚什么是面向对象编程,最简单直接的方式是去看看Alan Kay当初为什么会设计出smalltalk出来。(注:smalltalk被公认为世界上第一个面向对象语言,有的地方认为是Simula 67,此处不去讨论它)。而后的C++,更是明显的说明了这个问题。(注:C++为世界上第一个商业化的面向对象语言,前面所说的smalltalk和Simula 67都为实验室语言。)
回顾C++的历史,当时C语言已经非常的普及,它的高效完美及比汇编更加易用的特性使得很多人为之着迷。而后,随着软件行业的飞速发展,软件开发已经不是一件神秘的事情。而各行各业似乎都开始与软件产生了千丝万缕的关系。为止伴随而来的是许多行业对软件的大量需求,同时,诸如“航天工程”级别的大型软件需求也开始急剧增长,软件的复杂度也开始急剧飙升。
问题来的是如此的突然,这些问题几乎已经超出了一些语言的“理解范围”,比如,假设你的程序有几页纸长,或是超出了它的正常解题范围,那么像BASIC语言就可能会发生悲剧——可能永远不会算出结果。而当你的程序超过5万行的时候,C语言的程序员就会被各种命名冲突和各种隐藏在程序之中的小漏洞整的焦头烂额!
在很多时候,我们并不能在语言的理解范围之类解决问题,而且也没有清楚的文字告诉我们,语言的理解范围到底是什么!我们可能常常为增加额外的功能而试图在原来的系统中硬塞几行代码。但糟糕的是,与之伴随而来的便是软件额外的花费直线飙升!
大天使加百利终于出现了,也许,面向对象的概念就是在这种情况下诞生的。Smalltalk/C++也呼之而出。
其实C++诞生的原因很简单,第一个目地就是为了解决软件过于复杂,而使过程语言过于臃肿,以致超出了其“理解范围”所带来的各种难以发现和解决的BUG;第二个目地是为了解决开发大型项目时,为了增加开发效率,使用多人协同开发,而过程语言在这方面显得非常的吃力的问题。还有一个目地,就是让我们的代码更加易于理解。因为观察对象的实质,你会发现,我们建立的对象一般都是事实存在的一些事物,这比我们理解一类抽象更加有效,简单。
在面向对象发展了几十年的今天,当初的这些目地仍然被我们一直在使用,只不过,我们抽象出了这些东西,终于总结出了面向对象的本质:封装,继承,多态。
对!真正的面向对象编程必须具备这几个特征,不然,即使你使用了完全面向对象的语言来编程,最多也只能称之为基于对象编程。
而更抽象却更加易于理解的一句话就是,让你的代码“高复用,低耦合”,而我们前面所说的封装,继承,多态,只不过是为这六个字服务的而已。
这里,可能又会有人说,“我用的C#使用超基类Object继承而来的,我的方法也覆盖了原有的接口,这就是多态,所以我的程序就是面向对象的。”其实,这里,你已经走入了一个误区。就如我们前面总结的一样,如果你的代码并没有达到“高复用,低耦合”的目地,那么,你的思想仍然是停留在基于对象编程之上的。你要清楚,你所继承的Object这写类及框架,都是那些开发公司,如微软之类早已经做好的东西。你使用的是人家的产品,人家的产品具有面向对象的思想,而你,最多只能称之为微软的用户而已。