以前学C的时候,不用说自然就是用面向过程的想法来编程序的,而学了Java之后,感觉自己也就学会了面向对象,会用类定义,会编接口,会基于具有某种作用的接口来编一个实现它的类,然后再对这些类进行实例化。
可是我当时真的是理解了面向对象了吗,或许我当时是会用面向对象的形式来编代码,也会解释面向对象的内容,甚至能说得头头是道。但是我想我当时其实并不了解什么是面向对象,我只是会说,会用而已,并没有深层次的领悟,或许这个说得有点玄乎,但这是事实,如果没有真正经历过从面向过程到面向对象的转变,没有切身体会到面向对象的作用,及其出现的目的,是没有办法达到深层次的领悟的。
做这个编译器项目,虽然现在连1/10都没有真正完成,但是,就是因为用C来实作,让我经历了一个数据由零散到有规划的转变过程。而正是这个过程,让我理解到,一个有比较多数据量的项目的开发,它的数据是必须要有一个整体的规划的,如果不规划,那么它的零乱就必然导致整个开发过程的零乱,难以进行,而解决这个问题,就必须采用面向对象的思想,对数据进行有规划的分类统一管理。
为什么是“分类统一”呢?这正是我所理解到的面向对象的真正内涵。就是对数据共性的提取,将具有统一性的数据归入同一类,即归入同一个对象中来管理,而相应的,对数据的操作,就是这个对象自身的动作了。用面向对象的术语来讲,这些有共性的数据,就成了这个对象的属性,而相应的操作数据的动作,就成了这个对象的方法了。
所以面向对象,其实就是对数据的分类统一管理,以达到有规划地处理数据的效果的一种思想。因此照这么说来,面向对象它就只是一种思想,它不限语言,不管是面向过程的C语言还是面向对象的Java,其实只要达到了数据的分类统一管理,也就体现了面向对象。
语言是无所谓的,我们平常所说的面向对象语言和面向过程语言,其实它只是由于自身的特性而让它更适用于做面向过程或者面向对象,仅仅只是更适用而已,并不是只能。
说回一直被认为是面向过程的C,其实当它被用于数据量比较大的开发时,它同样是要做数据的统一分类,以达到有规划,易管理的效果。所以在C的开发里面,同样是可以体现面向对象的思想的。
我在项目里面,用到的C的OOP范式,大致如下:
一些模拟面向对象编程形式的预定义:
#ifndef C_OOD
#define C_OOD C_OOP
#define C_Class struct
#define C_Interface struct
#define C_Data struct
#define Integer int*
#define Int int
#define String char*
#define Char char
#define Boolean bool*
#define Bool bool
#define Void void
#endif
typedef C_Class Test_Object *Test_ObjectPt, Test_Object;
typedef C_Interface Test_Interface *Test_InterfacePt, Test_Interface;
typedef C_Data Test_Data *Test_DataPt, Test_Data;
类的定义:
C_Data Test_Data{//Test_Object类所需要的数据集合
Int Test1, Test2;
} ;
C_Interface Test_Interface {//Test_Object类所实现的接口
Void (*Test_Init) ();
Void (*Test_Do1) ();
Void (*Test_Do2) ();
};
C_Class Test_Object {//Test_Object类的定义
Test_Data test_Data;
Void (* Test_Release) (Test_ObjectPt);
Test_InterfacePt Test_iface;
};
接口的实际方法的编写:
Void FunInit (Test_DataPt test_Data, Int a, Int b)
{
test_Data -> Test1 = a;
test_Data -> Test2 = b;
}//接口的实际方法(进行类属性的初始化)
Void Fun1 (Int a)
{
printf ("%d\n", a);
}//接口的实际方法(执行对某个类属性的操作)
Void Fun2 (Int a, Int b)
{
printf ("%d\n", a + b);
}//接口的实际方法(执行对两个类属性的操作)
类的实例化及其属性的操作:
Void main (Int argc, Char **argv)
{
Test_Object iObj;//实例化Test_Object对象
Test_Interface iFace = {
FunInit,
Fun1,
Fun2
};//Test_Interface初始化(接口初始化)
iObj.Test_iface = &iFace;//让Test_Object对象实现接口Test_Interface
iObj.Test_iface -> Test_Init (&(iObj.test_Data), 1, 2);//调用iObj对象的方法进行属性初始化
iObj.Test_iface -> Test_Do2 (iObj.test_Data.Test1, iObj.test_Data.Test2);//调用iObj对象的方法对iObj对象里的属性进行操作
}
其实这个范式,还是有一些赘余的成分的,像一些typedef的预定义是很不必要的,它只会丢失了C简单自由的本性,我这里只是为了,跟面向对象语言的语法形式进行比较,便于理解,但实际用起来,我还是喜欢C的自由,代码看起来清爽,有个性,不会到处一个模样,本来C就该有C的样,不必刻意模仿。
————@Author CLinHF