上次看到一篇博客上解释面向过程和面向对象在实现需求上的区别:
需求:吃饭
面向过程:买食材,洗菜,切菜,炒菜,吃
面向对象:老板来份鱼香肉丝,吃
总结下来,面向过程就是把需求分化为一个个的步骤,然后按照步骤调用方法,实现需求;
面向对象为将事物抽象为对象,将数据和方法进行封装整体获取。
以此上可见,面向对象将事物看作一个个的抽象整体,更助于开发出高内聚,低耦合的程序,更加的易于拓展和维护。
不过不论是面向过程还是面向对象都是一种编程思想,与具体的语言无关,而说java和php等语言为面向对象语言,是其语言本身即支持封装、继承、多态等特征,而常被认为是面向过程的C语言也可以实现面向对象的程序,只是在使用面向对象的特性上需要麻烦一些。
抛开表象看本质。从本质概念上讲,面向对象大致有两个层次的内涵:
1、基于对象。就是题主所说的,只要把数据和函数放在一起就可以了。(外加普通的“继承”,不考虑多态的简单继承还算是基于对象的。)
2、多态。首先,方法可以在子类中重写;调用对象方法的时候,调用父类还是子类还是孙类的方法,能否自动选择到合适的呢?解决这个问题的设计就是“多态”。
实际上“基于对象”最重要、最常用、最根本。讨论问题本质的时候,甚至可以先不管多态。多态虽然很有用,但是如果把二者放在一起讨论,反而只会捣乱。
也就是说,要想理解透、用好面向对象,关键要理解透、用好基于对象 ,而这恰恰就是题主所说的,只要把属性和方法正确封装好,事情就成功了大半。
1、面向对象思想,有它很朴素、很自然的一面
我们常习惯说C语言是面向过程的语言,其实这话不大对,C语言完全可以写出面向对象的代码。因为C语言至少满足“把数据和方法封装在一起”这个基本要求,也有稍微高级点的写法实现继承和多态。
只要是写过一些实际代码的人应该都知道,无论编程语言如何简化,有一个基本功能肯定会用到——那就是把数据打包在一起。比如2D坐标需要把x和y放一起,复数需要把实部和虚部放一起,网购订单需要把单号、内容和价格放一起。
甚至退一步,回到1980年代的某些古老版本的C语言(结构体里不放函数),依然能写出符合面向对象思想的代码:
也就是说,基于对象本质是一个非常非常自然的概念。有了class或者struct,才能把数据放在一起,才能创建多个同类型的对象。没有struct,以上代码就没法很方便的表示多个学生。
无论谁来设计新的编程语言,几乎都会设计出类似的东西。
所以 基于对象 的概念十分容易掌握,只要合理定义了类的变量,事情就成了大半;再加上合理定义的操作(也就是方法或函数),就已经足够写出足够好的程序出来。
世界上有很多非常重要的程序,从操作系统到火控雷达,从火箭上天到载人登月,都就是用这种很朴素的思想写出来的。
2、现代的“面向对象”语言,到底干了些什么?
随着软件的进步,人们写的代码越来越多越来越复杂,不得不对语言规范做出更严格的控制,才能让软件规模进一步扩大。
这也是自然的过程,现在不管什么日常用品,都要考虑安全性、实用性、美观性,这是发展的趋势。
为了增强规范性,增强可读性,还要防止程序员犯傻,编程语言做了哪些事呢?举几个例子:
为加强权限管理,防止手滑修改变量,打造了一系列关键字,包括访问权限控制的public、private等。
Java和C#等语言,要求几乎所有的代码必须写在class内部,让面向对象更加纯粹。
继承和多态,为了它打造了一系列配套设施,比如C#至少就有virtual、override、new、protected、abstract、is、as等等有关的关键字。
static关键字,用于把属性和方法绑定到类本身,而不是对象。
“接口”的概念也和面向对象紧密相关,用它可以实现更灵活、更广泛的多态系统。当然相关的概念也多出来一堆。
因为需求是多变的,要想更好的满足需求,就要为语言不断添加新的特性。而解决问题的同时会带来另一些问题,让问题更加复杂。比如C++的const关键字就是一个典型的例子。
3、面向对象思想,只是众多程序设计思想之一
现代的“面向对象”思想发展到了一个很深入的程度,比如“设计模式”正是面向对象思想的典型例子。
设计模式的主要目标是让程序更易于扩展,“对修改封闭,对扩展开放”。也就是说理想情况下,任何新需求都能通过添加新模块解决,而不用修改老的代码。(虽然现实上有种种困难,但是这种做法在某些大型软件系统中也发挥了相当作用。)
但是要知道,越是接近现在,各种不同的设计思想越是百花齐放,各种思路也是平起平坐的关系。更多编程思想比如:
数据驱动编程(Data Driven Programming)。将程序架构的复杂度转移为结构化的数据表示,实现极其灵活的设计。
组件式编程。Unity采用了这种方式设计且获得了很大成功。组件式尽量用类的组合代替类的继承,但是依然保留了一些多态的特性。
Actor模型。与传统面向对象有良好兼容性,充分利用多核性能,在需要高性能并发的场合大放异彩。
函数式编程。比较古老的理念也焕发了新生。
当然,这些思想与面向对象并非对立,而是互为补充。
总之,退一步看。“面向对象”的种种高级特性,有时很有用,有时会被其它方式取代。而“基于对象”这一思想由于是极端朴素的,所以拥有不可替代性。无论一百年后代码怎么写,你可能都需要把相关的数据和方法打包在一起。
要去学习、去探索正确的方法,而不必拘泥于方法的名字和形式。