< 返回博客

关于函数分派在面向对象和面向过程中的作用的思考


面向对象是对面向过程的总结与约束。

面向对象的出现是必然的,这一点从人类理性的工作方式就可以得到解释。
在面向过程的范式中,函数是最基本的“动态”抽象元素,这是通过对汇编的总结和约束得来的。
实际上,面向对象也一样,函数,或者说方法也同样是最基本的元素,因为我们完全可以将字段当作隐式调用的方法。
所以说,面向过程与面向对象都是以方法为核心的范式,它们之间的不同之处在于方法的组合方式上,面向过程的所有方法平铺在一层上面,而面向对象通过各种手段(类的区分、重载、重写等)使得方法的组合有了层次,这种组合方式的不同也正体现了面向对象的抽象层次更高。更直观的看,它们二者的不同之处在于方法的查找方式上,正是通过查找方式的不同才实现了组合方式的不同。
在面向过程中,函数被“函数名”唯一确定,或者说,只需要函数名这一个宗量就可以确定一个函数。而面向对象则使用更多的宗量才能确定一个函数(方法)。但只从这一点来看,它仍未获得面向过程所不拥有的特征,它们本质上是一样的。经历了以下过程,面向对象的世界才算建立起来。这种通过宗量查找函数的过程称为函数分派。

只有当为宗量赋予更多特殊意义时,面向对象中的各种概念才真正出现。这个赋予意义的过程也正是我们将自己对世界的理解融入其中的过程。
我们为第一个宗量赋予“对象名”的意义,对象的概念便出现了,因为我们通过第一个宗量将方法“捏成”一簇一簇。
我们从面向过程那里保留了“函数名”这个宗量,也就出现了对象中的方法。
我们将函数参数也作为宗量,这才出现了对象内的函数重载。
继承的出现使得方法的组合更为灵活,对象之间有了垂直方向上的联系。继承本质上是特征的沿用、拓展与修改,特征则体现为方法。
多态的出现则引出了“实际类型”和“外观类型”两个概念。这是因为在多态中,有些地方需要子类实例以父类实例的身份出现,那么这个对象就同时拥有了两重身份,我们需要表达这两者,这两个概念也就应运而生。“实际类型”是对象生来就有的,它表达了一个对象所拥有的所有特性,而“外观类型”是多变的,它表达了对一个对象所拥有特性的截取。
虽然“外观类型”使得对象看起来像是个父类的实例,但实际上它仍表现出子类的特性,也就是说,分派过程中不能看到一个A的实例就去查询A类的函数,这相当于增加了一个不确定的宗量。也正是这一点,导致了面向对象中函数分派方式分为两种:以“外观类型”分派和以“实际类型”分派。以实际类型进行分派的函数我们称为“虚函数”,以外观类型分派的则是“非虚函数”。

面向对象的三大特征:抽象、继承、多态。其中,抽象使得方法组合成为一个个概念,继承使得它们得以复用,这两者实际上是创建概念的过程,而真正使得拥有继承关系的概念有所联系、共同工作的,实际上只有多态。