Javascript多线程引擎(四)
因为使用C语言做为开发语言, 而C语言在类的支持方面几乎为零, 而Javascript语言的Object类型是一个非常明显的类支持对象,所以这里需要提出一个方案对Object类型的继承进行支持.
本章节介绍一个简单的基于C语言单继承结构的实现, 实现非常的简单, 但是体现了Java 的OO思想.
1 ////Object.h 2 #ifndef _Object_ 3 #define _Object_ 4 /******************* 5 cls: 6 类似于Java的接口, 子类想对某个函数进行重载 , 7 则只要在具体同名函数的位置替换掉原先的指针 . 8 而子类想访问被覆盖掉的父类同名函数, 则直接访问 9 父类的函数指针. 10 而私有函数, 则都在.c 文件中 11 pb: 12 公共数据结构, 数据结构在.h中 13 通过指针来访问自己的和父对象的公用数据 14 ((struct Pb*)pb[0])->size ; 访问了跟对象的public block的size 15 sb: 16 私有的数据成员, 数据结构在.c中, 非本对象不可操作 17 ((struct Sb*)sb[0])->size 18 FLOOR: 19 该对象处于继承链的第几个位置, Root 为 0 20 注: pb 和 sb的 数据槽 都由new Object的对象来申请空间 21 初始化的方向为先初始化父类 22 析构方向为先析构子类 23 ********************/ 24 struct Object; 25 //接口操作 26 typedef void (*PrintFn)(struct Object* self); 27 #define OBJECT_FLOOR 0 28 struct Class{ 29 PrintFn p; 30 }; 31 //公布的操作 32 struct Pb{ 33 int size; 34 }; 35 struct Object{ 36 struct Class* cls; 37 void** pb; 38 void** sb; 39 }; 40 void ObjectPrint(struct Object* self); 41 //申请基本的空间 42 //构建一个基本的空间, floor为子类所在的层, 根为第0层 43 struct Object* AllocObject(int floor); 44 //初始化对象 45 //如果o == NULL, 则Alloc一个空间 46 struct Object* CreateObject(struct Object* o); 47 #endif
通过Cls公布类似java接口操作, 而pb 和 sb 分别为公布数据结构和私有数据结构, 并且私有函数都写在 .c 文件中.
1 //Object.c 2 #include<stdlib.h> 3 #include<stdio.h> 4 #include"Object.h" 5 6 struct Sb{ 7 int num; 8 }; 9 void ObjectPrint(struct Object* self){ 10 struct Pb* p; 11 struct Sb* s; 12 p = (struct Pb*)self->pb[OBJECT_FLOOR]; 13 s = (struct Sb*)self->sb[OBJECT_FLOOR]; 14 printf("root Object Pb: %d\n root Object Sb: %d\n", p->size,s->num); 15 } 16 //申请基本的空间 17 //构建一个基本的空间, floor为子类所在的层, 根为第0层 18 struct Object* AllocObject(int floor){ 19 if(floor <= 0){ 20 //error 21 } 22 floor ++; 23 struct Object* o; 24 o = (struct Object*)malloc(sizeof(struct Object)); 25 o->cls = (struct Class* )malloc(sizeof(struct Class)); 26 //数据槽 27 o->pb = (void**) malloc(sizeof(void*) * floor ); 28 o->sb = (void**) malloc(sizeof(void*) * floor ); 29 } 30 31 //初始化对象 32 //如果o == NULL, 则Alloc一个空间 33 struct Object* CreateObject(struct Object* o){ 34 if(o == NULL) 35 o = AllocObject(OBJECT_FLOOR); 36 //初始化pb数据块 37 o->pb[OBJECT_FLOOR] = (struct Pb*)malloc(sizeof(struct Pb)); 38 //初始化sb数据块 39 o->sb[OBJECT_FLOOR] = (struct Sb*)malloc(sizeof(struct Sb)); 40 o->cls->p = &ObjectPrint; 41 ((struct Pb*)o->pb[OBJECT_FLOOR])->size = 1; 42 ((struct Sb*)o->sb[OBJECT_FLOOR])->num = 2; 43 return o; 44 }
私有数据结构实现在.c 中, 私有函数也实现在.c 中
而下面就是一个简单的Object2.h 对象
1 ///Object2.h 2 #ifndef _Object2_ 3 #define _Object2_ 4 #define OBJECT2_FLOOR 1 5 #include"Object.h" 6 //新子类的共享数据 7 struct Pb2{ 8 int size; 9 }; 10 void ObjectPrint2(struct Object* self); 11 struct Object* CreateObject2(struct Object* o); 12 #endif
Object2.h 实现了自己的数据结构 和公布了一个多态函数
1 ///Object2.c 2 #include"Object.h" 3 #include"Object2.h" 4 #include<stdio.h> 5 #include<stdlib.h> 6 void ObjectPrint2(struct Object* self){ 7 struct Pb2* p = (struct Pb2*)self->pb[1]; 8 printf("Object2 : %d \n",p->size); 9 ObjectPrint(self); 10 } 11 struct Object* CreateObject2(struct Object* o){ 12 if(o == NULL) 13 //处于继承链第一个位置 14 o = AllocObject(OBJECT2_FLOOR); 15 //初始化父对象 16 CreateObject(o); 17 //初始化pb数据块 18 o->pb[OBJECT2_FLOOR] = malloc(sizeof(struct Pb2)); 19 //初始化sb数据块 20 o->sb[OBJECT2_FLOOR] = NULL; 21 //重载 22 o->cls->p = &ObjectPrint2; 23 ((struct Pb2*)o->pb[OBJECT2_FLOOR])->size =3; 24 return o; 25 }
在第9行 , 调用了父类的该同名函数.
以下是一个基本的测试:
////main.c #include"Object2.h" #include<stdlib.h> int main(){ struct Object* o = CreateObject2(NULL); o->cls->p(o); }
编译命令:
gcc -c Object.c
gcc -c Object2.c
gcc -c main.c Obejct.o Object2.o
./a.out
测试成功!
通过pb 的连续内存块, 在继承结构中, 对象只能看到它自己和父对象的内存结构, 而不能发现该对象的子对象内存结构, 而父对象则照常使用属于他自己的内存空间, 从而实现了信息隐藏.
并且每个对象的访问数据和操作都是统一的(主要是父对象):
1. 子对象指针和父对象指针都可以通过pb数据块进行操作自己的数据(从共享内存中找到自己的内存地址)
2. 子对象和父对象指针访问API都指向正确的实现(可以访问重载函数)
3. 私有数据都是从sb数据块获取
C语言的继承和多态主要的核心是内存结构和CPU访问数据和函数的方式(参考C++对象继承内存模型), 或者采用动态语言的机制进行查询访问.