一、程序员的计算机
程序员的计算只由两样东西组成:CPU和存储器。
存储器是一组集成电路,其中每个能保存一个数字的电路为一个单元,这些单元依次编号作为地址,就跟街上的房子的门牌号码一样。
CPU是一块集成电路,它能自动从特定存储单元开始,顺序读取存储单元,并执行读入的数字所代表的算术以修改其它存单元。这些存储单元中特定的数字代表跳到读写某个地址的存储单元,这时CPU就不再是顺序存取存储单元了。
程序员管存储器单元中代表CPU动作的数字叫指令,CPU执行指令时使用的数字就叫操作数,或者省事点叫数据。程序员把指令数字和代表操作数的数字组合成CPU认识的数字,程序员管这种数字叫机器码。操作数可能用其值直接组合进机器码,也可能用它所在的地址组合进机器码,这得看程序员的心情了。
二、程序员的问题
程序员要解决一个问题,就当玩一场数字游戏,搞清楚游戏的内容和规则后,约定好表示内容和规则的数字,把它们排列进存储器,交给CPU玩。
三、程序员的程序
程序员看着程序,他看见了一块存储空间。
当程序员写程序时,存储空间通常以文本的形式存在,通常用宏观的指令和表示数据含义的符号写成,他管它叫源码空间。
然后程序员把组织好的源码空间交给一种叫程序,他知道这种程序会把收到源码的每条命令分解成若干条机器指令,在"程序虚地址空间"按排每条指令和操作数的地址。他觉得这种程序就象一个翻译,把他的语言翻译成机器的语言,又象一个编织工人把数字这种零件按排拼装成一块虚存储器,所以给它取了个好听的名字:编译器。
当程序员运行程序时,"程序虚地址空间"被另一种程序装进实在的存储块中,并将所有对虚地址的引用换算成实际的存储器地址。这种程序的名字当然是程序载入器了。
程序员心情好的时候也会亲自动手编织数字来写程序,早的时候许多程序都是这样写出来的,其中显然有编译器这种程序。
四、程序员的对象
程序员似乎不擅长处理复杂而微妙的关系,于是纷纷开始琢磨搞对象。
对象还是一段存储单元,其中若干个连续单元里的数字表示一项数据或宏观指令,程序员称之为对象成员。对象成员存储单元里的数字可能有指令、数据或地址,而地址所代表的存储单元里可能存放着指令、数据、对象或地址,程序员管它们叫方法成员、字段成员、对象聚合、引用。
程序员最关心对象成员的个数、含义和排列顺序,只要知道这些,他就知道该那块存储单元的结构和用法,所以管这些信息叫接口。如果两个对象具有相同的接口,程序员就用同样的方式读写它们,所以管它们叫同类对象。
同类对象的方法指令内容显然是一样的,如果在每个对象的存储块里复制一份显然很浪费,而有些同类对象的字段成员内容也是完全一样的。程序员也感到一次又一次的重复写这些对象很麻烦,就把这些同类对象中相同的部份组织到一块存储单元中,称之为类。然后申明在对象中只保留这块共享存储单元的地址以示它属于该类。
有时候程序员会制造有很多个成员的对象来表示复杂的事物,比如一个已成家中年男中学教师对象,有表示其为人夫方面的成员,有表示其为人父方面的成员,有表示其为人师方面的成员,显然把某一方面相关的成员放到一起会自然,而程序员也很自然的认为这些成员是与对象这方面特性打交道的接口,更自然的认为取得了这一段连续成员的起点地址就得到该接口。
有时存储单元大小结构不同的异类对象,在不同位置上会有一段连续的相同成员,并且这些成员代表对象某方便特征或行为能力,比如说青年女中学教师也具有为人师的接口。这时程序员就认为把两者的为人师接口地址取得之后就得到了两个同类对象:教师。
五、对象程序员的编译器
与普通编译器一样,源码中的类、对象及成员名字符号与虚程序地址空间的对应是由编译器完成的。
但是对象程序员的编译器会做很多复杂的,以前要程序员自己处理的事情。
编译器把源码空间的名字修改成内部名字,然后为内部名字分配所需要的存储单元,并根据引用源码空间名字的上下文决定实际引用的地址。对象程序员往往在对象源码中定义许多同样名字但参数不同的方法。
对象程序员有时在对象源码中申明具有某些接口,然后用任意顺序编写其成员。编译器会重新按接口的要求组织成员的存储单元。
编译器还会把类型信息存储块附加给对象,以便在运行时也可以使用源码空间的名字。
六、对象程序员的虚拟机
对象程序员看不见计算机,在他看来,有一台逻辑上的机器,完成了程序运行时他写的程序需要一切支持。
虚拟机会为程序分配内存块,将程序里的数字复制到内存块中,将其中代表地址的数字修正为实际的存储单元编号,形成进程。
进程内的对象通常直接使用对象接口的地址或名字进行通信。
虚拟机能把同一块内存单元与不同进程的地址空间对应起来,进程间的对象可以使用这块内存单元进行通信。程序员称之为进程间通信IPC.
必要时虚拟机能够为不同进程内的对象提供通信代理,对象把访问要求传给代理,代理找到响应对象并完成调用和结果回送。
七、对象程序员的世界观
一切都是对象,对象就是存储块。
八、对象程序员的辩证法
封装、继承和多态是抽象公共接口与实现多样行为的对立统一。
通过内部名字、方法指针、虚方法表、基类成员拷贝等内存标记、操纵技巧实现这种对立统一。
九、对象程序员的口胃
甜。面象对象编程语言不过是些语法糖,如果能洞悉语法背后的内幕,那么吃起来就象酒心巧克力,如果迷惑于表面,那吃起来就象牛皮糖。
十、对象程序的诞生
面象对象编程诞生那天,面象对象程序员也就诞生了。
对象程序,只是含义为指令和操作数的数字序列,两者没有形式差别,于是编程必须小心翼翼,不要混肴。
从实践中,人们领悟到人为把指令和操作数分成不同的存储块是极为方便的,于是发明了运行时堆栈框架;为了减少重复节省存储器程序员们发明了子程序调用;为了解决复杂问题,程序员又发明了结构化编程和模块化。
然而对于涉及大量数据、模块的复杂动态系统,即使是模块化开发也是极为麻烦的,即使小心翼翼也难于应付。
于是人们醒悟:我们不关心程序的指令,那是静态的,暂时的,我们需要的是数据,那才是结果所在。
于封装被发明了:把一组数据及操纵方法放到一起,视为逻辑整体,通过接口访问。
新世界的大门打开了。