热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

自己写PHP扩展之实现类的继承[原创]

自己写PHP扩展之实现类的继承[原创]

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

1
2
3
4
5
6
7
8
classSecure{
    publicfunctiontest(){
           echo"this is Secure::test";
    }
}
classSirenextendsSecure{
  
}

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

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

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

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

3.在PHP_MINIT_FUNCTION中注册两个类 这里是重点哦

1
2
3
4
5
6
7
8
9
10
PHP_MINIT_FUNCTION(secure){
        zend_class_entry secure;
        zend_class_entry siren;
        INIT_CLASS_ENTRY(secure,"Secure",secure_methods);//初始化
        INIT_CLASS_ENTRY(siren,"Siren",siren_methods);//初始化  上一章都详细介绍过
        secure_ce=zend_register_internal_class_ex(&secure,NULL,NULL TSRMLS_DC);
        secure_ce->ce_flags=ZEND_ACC_IMPLICIT_PUBLIC;
        siren_ce=zend_register_internal_class_ex(&siren,secure_ce,NULL TSRMLS_DC);
        returnSUCCESS;
};

第2-3行 //创建对象..secure和siren
第4-5行 对两个对象进行初始化 上一章有详细介绍过.
第 6 行 注册类
第 7 行 要把secure_ce声明为一个普通类,这里一定要设置,不然 默认会是final类.这样继承会报错.
除了 ZEND_ACC_IMPLICIT_PUBLIC 还有很多 类似功能的宏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ZEND_ACC_ABSTRACT
ZEND_ACC_ALLOW_STATIC
ZEND_ACC_CALL_VIA_HANDLER
ZEND_ACC_CHANGED
ZEND_ACC_CLONE
ZEND_ACC_CLOSURE
ZEND_ACC_CTOR
ZEND_ACC_DEPRECATED
ZEND_ACC_DTOR
ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
ZEND_ACC_FINAL
ZEND_ACC_FINAL_CLASS
ZEND_ACC_IMPLEMENTED_ABSTRACT
ZEND_ACC_IMPLEMENT_INTERFACES
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS
ZEND_ACC_IMPLICIT_PUBLIC
ZEND_ACC_INTERACTIVE
ZEND_ACC_INTERFACE
ZEND_ACC_PPP_MASK
ZEND_ACC_PRIVATE
ZEND_ACC_PROTECTED
ZEND_ACC_PUBLIC
ZEND_ACC_SHADOW
ZEND_ACC_STATIC

根据名字就能看出来,这里就不做一一介绍了.
第 8 行 把siren注册到我们的Hash表里面.注意zend_register_internal_class_ex的第二个参数
zend_register_internal_class_ex(``,``,``)
第二个参数就是 父类的指针.
该函数会调用 zend_do_inheritance 将parent_ce的 属性 类 复制到 class_entry里
定义如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
ZEND_APIvoidzend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC)/* {{{ */
{
        if((ce->ce_flags & ZEND_ACC_INTERFACE)
                && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
                zend_error(E_COMPILE_ERROR,"Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
        }
        if(parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
                zend_error(E_COMPILE_ERROR,"Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
        }
  
        ce->parent = parent_ce;
        /* Copy serialize/unserialize callbacks */
        if(!ce->serialize) {
                ce->serialize   = parent_ce->serialize;
        }
        if(!ce->unserialize) {
                ce->unserialize = parent_ce->unserialize;
        }    
  
        /* Inherit interfaces */
        zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
  
        /* Inherit properties */
        zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, zval_property_ctor(parent_ce, ce), NULL,sizeof(zval *), 0);
        if(parent_ce->type != ce->type) {
                /* User class extends internal class */
                zend_update_class_constants(parent_ce  TSRMLS_CC);
                zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
        }else{
                zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
        }
        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);
  
        zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL,sizeof(zval *), 0);
        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);
        do_inherit_parent_constructor(ce);
  
        if(ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
                ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
        }elseif(!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) {
                /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
                zend_verify_abstract_class(ce TSRMLS_CC);
        }
}

4.添加方法体

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

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


推荐阅读
  • 本文对元代诗人许有壬的《琳宫词次安南王韵》进行了详细的译文解读和原文赏析,旨在深入理解诗中的意境与艺术特色。 ... [详细]
  • 本文详细介绍了企业内部的主要管理层级,包括董事会、首席执行官(CEO)及总裁、总经理等角色的定义与职责。 ... [详细]
  • Windows环境下Oracle数据库迁移实践
    本文详细记录了一次在Windows操作系统下将Oracle数据库的控制文件、数据文件及在线日志文件迁移至外部存储的过程,旨在为后续的集群环境部署做好准备。 ... [详细]
  • 本文探讨了当通过Nginx访问网站时出现504 Gateway Timeout错误的解决方案,特别是当请求处理时间超过30秒时的情况。文章提供了调整PHP-FPM配置的具体步骤,以延长请求超时时间。 ... [详细]
  • 作为一名即将步入职场的应届毕业生,我在选择职业路径时面临两个选项:SAP的ABAP开发或大数据技术。对于SAP领域,我的目标是成为一名顾问。面对这两个方向,哪一个具有更好的发展前景,哪一个更容易上手?希望各位前辈能提供一些见解。 ... [详细]
  • 狮子数学:第六百零五章 阿贝尔定理(第九十九讲)
    本章节深入探讨了阿贝尔定理的核心内容及其在数学分析中的应用,通过具体的例子和详细的证明过程,帮助读者更好地理解和掌握这一重要理论。 ... [详细]
  • Adversarial Personalized Ranking for Recommendation
    目录概主要内容基础对抗扰动对抗训练细节代码HeX.,HeZ.,DuX.andChuaT.Adversarialpersonalizedrankingforrecommendatio ... [详细]
  • 本文详细介绍了PHP中几个常用的数组回调函数,包括array_filter、array_map、array_walk和array_reduce。通过具体的语法、参数说明及示例,帮助开发者更好地理解和使用这些函数。 ... [详细]
  • 本文详细探讨了PHP中使用const和define定义常量的方法及其差异。了解这些区别有助于开发者根据具体需求选择合适的方式定义常量。 ... [详细]
  • 本文介绍了一个来自AIZU ONLINE JUDGE平台的问题,即清洁机器人2.0。该问题来源于某次编程竞赛,涉及复杂的算法逻辑与实现技巧。 ... [详细]
  • 深入解析Java SE、Java EE和Java Web的核心知识体系
    通过一系列图表全面解析Java SE、Java EE与Java Web的核心知识体系,帮助开发者快速掌握这些关键技术领域的要点。 ... [详细]
  • 本文详细探讨了如何根据不同的应用场景选择合适的PHP版本,包括多版本切换技巧、稳定性分析及针对WordPress等特定平台的版本建议。 ... [详细]
  • 本文探讨了如何使用Scrapy框架构建高效的数据采集系统,以及如何通过异步处理技术提升数据存储的效率。同时,文章还介绍了针对不同网站采用的不同采集策略。 ... [详细]
  • 使用CorelDRAW X7轻松绘制卡通风格杯子教程
    本文将引导您通过CorelDRAW X7软件,利用贝塞尔工具和交互式填充功能,创作出一个既可爱又生动的卡通杯子。我们将详细介绍每个步骤,帮助您掌握绘制技巧。 ... [详细]
  • egg实现登录鉴权(七):权限管理
    权限管理包含三部分:访问页面的权限,操作功能的权限和获取数据权限。页面权限:登录用户所属角色的可访问页面的权限功能权限:登录用户所属角色的可访问页面的操作权限数据权限:登录用户所属 ... [详细]
author-avatar
暮色归家
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有