一、编程的任务
编程只是分配做以下三件事:1)描述要计算什么;2)将计算序列分解成小的步骤;3)计算时管好内存分配。
也许,如何分配这三件事的工作,也是低级语言与高级语言的一点差别所在吧。毫无疑问,1)是所要解决的主要任务,属于“问题域”的核心问题;而2)、3)只是类似“行政工作”的辅助任务而已,只是“实现域”中琐碎的具体手段。理想状态下,我们只需把注意力集中在1)上面,而不用为2)、3)分心。如果由Computer本身自动处理“行政工作”,由Programmer关注业务层面的分析、设计和编码,编程的过程会直接、容易得多吧。
或许,判断某种语言构造的高低也有了一个标准:是否移除了足够的“行政工作”。从这个角度来说,C不是高级语言,C++也不是合格的高级语言:(,当然也不能抹杀C++中的模板和泛型。伴随语言的演化过程,我们的关注焦点也是逐渐提前、逐渐缩小。Joyner甚至认为,高级语言最重要的特性就是免去程序员进行这些琐碎的行政工作之苦,“这一特性比‘面向对象’本身更重要,应当是所有现代编程方法的内在本性”。
二、类型的作用
很多语言,记得刚开始学习的第一步,都是类型。提到类型,这总会没来由的让我想起亚里士多德提出的对西方文明作出巨大贡献的动物分类系统。动物有有血的、无血的,程序中的变量有整型的、有字符型的等等。其中的区别,也许在于动物之间不能像程序里的变量一样强制转换吧 -_-!
编程语言里,类型系统是做什么的,为什么需要类型?Cardelli说,“类型系统的基本作用在于避免程序在运行过程的执行错误”。简而言之,类型定义了实体的属性与行为,而类型系统的作用,就在于基于语法检查之上,负责对实体的操作是否符合该类型所定义的属性的检查,也就是语义层面的检查。
按照类型系统,程序语言可以分为有类型的和无类型的。对于有类型的语言,静态的类型检查语言与动态类型检查的语言的区别在于前者在编译时就能保证只有合法的操作才能施与某一类型的实体。
随着编程语言的演进,类型与类型系统也在不停地发展。从FORTRAN、COBOL到ALGOL,改进编程语言的办法是发明新的编程语言来处理不同种类的实体。自从OO之后,以类为媒介,我们可以自己定义自己所需的类型,因为语言本身已经提供了扩充语言已有实体的机制。
三、封装或隐藏
提到OO,就不能不提到OO的三驾马车之首:封装。是的,我们都知道封装,可是封装什么呢?首先把数据和操作揉合到一起,然后就开始把数据隐藏?
封装的目的是隐藏数据么?如果一个实体把关于数据的一切都隐藏了,这个实体还有什么意义呢?存储数据的真正目的是是数据可以访问而不是拒绝访问或是隐藏他们。噫,难道是隐藏操作?哈,把数据公开把操作隐藏,那可是一个标准的结构体,和OO无关。
翻开书本,封装encasulation的定义是“to enclose in or as in a capsule”,在OO中的作用在于保护类的实现部分不受外界破坏。关键在于,实现和接口的分离。我们要隐藏的既不是数据也不是操作而是实现,我们要公开的既不是数据也不是操作而是接口。把所有的数据都设为private然后写上一堆的get、set 函数是令人厌烦的,想想C#提供的属性都作了些什么:公开的一致的接口界面,和隐藏起来的Get、Set的计算细节。
某个曾经在《程序员》上大放厥词的公司的CTO说到,“面向对象把数据结构包在对象里面,外面的功能就不再受数据结构的变化的影响”,但是“对于大型企业的业务系统来说,数据是长期稳定的,业务过程或者说对象的接口才是变化无穷”,所以“对象包装了稳定的东西,把不稳定的东西暴露出来”,导致了“从总体上看,软件还是不稳定”。哦不,面向对象编程并不是用来解决业务层面复杂多变的需求变更的灵药,尤其是如果前期没有作好面向对象分析和面向对象设计的时候。同时,OO的封装也并不是把数据藏进去,把方法签名拉出来那么简单。真正要隐藏的,仅仅是对接口的实现方式而已,数据并不是天生隐藏的~~