自己寫PHP擴展之實現類的繼承

openkk 12年前發布 | 4K 次閱讀 Ubuntu14

聲明:本文為斯人原創,全部為作者一一分析得之,有不對的地方望賜教。
歡迎轉載,轉載請注明出處 。
本文地址:http://imsiren.com/archives/593

如果我們想繼承某一個類,我們怎么辦?

比如 Siren類繼承Secure類.

</div>

  1. class Secure{  
  2.     public function test(){  
  3.            echo "this is Secure::test";  
  4.     }  
  5. }  
  6. class Siren extends Secure{  
  7.    
  8. }  
  9. </ol> </div>
    這樣一個類,該怎么做?
    其實沒有什么大不同,跟創建一個普通類是一樣的..只是有一些稍作改動..
    1.在頭文件中聲明方法

    </div>

    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);  
    8. </ol> </div>

      2.在c文件中 創建 method指針,注意 要一一對應.secure_method和 siren_method不能放在一個指針里.

      </div>

      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. };  
      12. </ol> </div>
        3.在PHP_MINIT_FUNCTION中注冊兩個類 這里是重點哦

        </div>

        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. };  
        11. </ol> </div>
          第2-3行 //創建對象..secure和siren
          第4-5行 對兩個對象進行初始化 上一章有詳細介紹過.
          第 6 行 注冊類
          第 7 行 要把secure_ce聲明為一個普通類,這里一定要設置,不然 默認會是final類.這樣繼承會報錯.
          除了 ZEND_ACC_IMPLICIT_PUBLIC 還有很多 類似功能的宏
          </div>

          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  
          25. </ol> </div> 根據名字就能看出來,這里就不做一一介紹了.
            第 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里
            定義如下

            </div>

            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. }  
            45. </ol> </div>

              4.添加方法體

              </div>

              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. };  
              16. </ol> </div>
                這樣 Siren類就繼承了 Secure類
                在php里面 執行
                $a=new Siren();
                $a->test();
                就會輸出”this is Secure::test”

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

               本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
               轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
               本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!