自己写PHP扩展之实现类的继承

12年前
声明:本文为斯人原创,全部为作者一一分析得之,有不对的地方望赐教。
欢迎转载,转载请注明出处 。
本文地址:http://imsiren.com/archives/593

如果我们想继承某一个类,我们怎么办?

比如 Siren类继承Secure类.

  1. class Secure{  
  2.     public function test(){  
  3.            echo "this is Secure::test";  
  4.     }  
  5. }  
  6. class Siren extends Secure{  
  7.    
  8. }  

这样一个类,该怎么做?
其实没有什么大不同,跟创建一个普通类是一样的..只是有一些稍作改动..
1.在头文件中声明方法

  1. zend_class_entry *secure_ce;  
  2. zend_class_entry *siren_ce;  
  3.         PHP_METHOD(Secure,__construct);  
  4.         PHP_METHOD(Secure,__destruct);  
  5.         PHP_METHOD(Secure,test);  
  6.         PHP_METHOD(Siren,__construct);  
  7.         PHP_METHOD(Siren,__destruct);  

2.在c文件中 创建 method指针,注意 要一一对应.secure_method和 siren_method不能放在一个指针里.

  1. const zend_function_entry secure_methods[]={  
  2.         PHP_ME(Secure,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)  
  3.         PHP_ME(Secure,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)  
  4.         PHP_ME(Secure,test,NULL,ZEND_ACC_PUBLIC)  
  5.         PHP_FE_END  
  6. };  
  7. const zend_function_entry siren_methods[]={  
  8.         PHP_ME(Siren,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)  
  9.         PHP_ME(Siren,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)  
  10.         PHP_FE_END  
  11. };  

3.在PHP_MINIT_FUNCTION中注册两个类 这里是重点哦
  1. PHP_MINIT_FUNCTION(secure){  
  2.         zend_class_entry secure;  
  3.         zend_class_entry siren;  
  4.         INIT_CLASS_ENTRY(secure,"Secure",secure_methods);//初始化  
  5.         INIT_CLASS_ENTRY(siren,"Siren",siren_methods);//初始化  上一章都详细介绍过  
  6.         secure_ce=zend_register_internal_class_ex(&secure,NULL,NULL TSRMLS_DC);  
  7.         secure_ce->ce_flags=ZEND_ACC_IMPLICIT_PUBLIC;  
  8.         siren_ce=zend_register_internal_class_ex(&siren,secure_ce,NULL TSRMLS_DC);  
  9.         return SUCCESS;  
  10. };  

第2-3行 //创建对象..secure和siren
第4-5行 对两个对象进行初始化 上一章有详细介绍过.
第 6 行 注册类
第 7 行 要把secure_ce声明为一个普通类,这里一定要设置,不然 默认会是final类.这样继承会报错.
除了 ZEND_ACC_IMPLICIT_PUBLIC 还有很多 类似功能的宏
  1. ZEND_ACC_ABSTRACT  
  2. ZEND_ACC_ALLOW_STATIC  
  3. ZEND_ACC_CALL_VIA_HANDLER  
  4. ZEND_ACC_CHANGED  
  5. ZEND_ACC_CLONE  
  6. ZEND_ACC_CLOSURE  
  7. ZEND_ACC_CTOR  
  8. ZEND_ACC_DEPRECATED  
  9. ZEND_ACC_DTOR  
  10. ZEND_ACC_EXPLICIT_ABSTRACT_CLASS  
  11. ZEND_ACC_FINAL  
  12. ZEND_ACC_FINAL_CLASS  
  13. ZEND_ACC_IMPLEMENTED_ABSTRACT  
  14. ZEND_ACC_IMPLEMENT_INTERFACES  
  15. ZEND_ACC_IMPLICIT_ABSTRACT_CLASS  
  16. ZEND_ACC_IMPLICIT_PUBLIC  
  17. ZEND_ACC_INTERACTIVE  
  18. ZEND_ACC_INTERFACE  
  19. ZEND_ACC_PPP_MASK  
  20. ZEND_ACC_PRIVATE  
  21. ZEND_ACC_PROTECTED  
  22. ZEND_ACC_PUBLIC  
  23. ZEND_ACC_SHADOW  
  24. ZEND_ACC_STATIC  
根据名字就能看出来,这里就不做一一介绍了.
第 8 行 把siren注册到我们的Hash表里面.注意zend_register_internal_class_ex的第二个参数
zend_register_internal_class_ex(``,`< zend_class_entry *parent_ce>`,`< char *parent_name TSRMLS_DC>`)
第二个参数就是 父类的指针.
该函数会调用 zend_do_inheritance 将parent_ce的 属性 类 复制到 class_entry里
定义如下
  1. ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */  
  2. {  
  3.         if ((ce->ce_flags & ZEND_ACC_INTERFACE)  
  4.                 && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {  
  5.                 zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);  
  6.         }  
  7.         if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {  
  8.                 zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);  
  9.         }  
  10.    
  11.         ce->parent = parent_ce;  
  12.         /* Copy serialize/unserialize callbacks */  
  13.         if (!ce->serialize) {  
  14.                 ce->serialize   = parent_ce->serialize;  
  15.         }  
  16.         if (!ce->unserialize) {  
  17.                 ce->unserialize = parent_ce->unserialize;  
  18.         }      
  19.    
  20.         /* Inherit interfaces */  
  21.         zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);  
  22.    
  23.         /* Inherit properties */  
  24.         zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);  
  25.         if (parent_ce->type != ce->type) {  
  26.                 /* User class extends internal class */  
  27.                 zend_update_class_constants(parent_ce  TSRMLS_CC);  
  28.                 zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);  
  29.         } else {  
  30.                 zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);  
  31.         }  
  32.         zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);  
  33.    
  34.         zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);  
  35.         zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);  
  36.         do_inherit_parent_constructor(ce);  
  37.    
  38.         if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {  
  39.                 ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;  
  40.         } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) {  
  41.                 /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */  
  42.                 zend_verify_abstract_class(ce TSRMLS_CC);  
  43.         }  
  44. }  

4.添加方法体
  1. PHP_METHOD(Secure,__construct){  
  2.         php_printf("construct is running");  
  3. };  
  4. PHP_METHOD(Secure,__destruct){  
  5.    
  6. };  
  7. PHP_METHOD(Secure,test){  
  8.         php_printf("this is Secure::test");  
  9. };  
  10. PHP_METHOD(Siren,__construct){  
  11.    
  12. };  
  13. PHP_METHOD(Siren,__destruct){  
  14.    
  15. };  

这样 Siren类就继承了 Secure类
在php里面 执行
$a=new Siren();
$a->test();
就会输出”this is Secure::test”

原文出处:http://imsiren.com/archives/593