浅谈PHP源码二十八:关于类结构和继承
作为html' target='_blank'>面向对象中一个非常关键也非常纠结的特性,我们需要了解一些
在PHP5中,从一开始就有了继承的概念,今天我们从PHP源码出发,了解他是怎么实现的。
在了解类的继承之前,我们需要知道类在PHP源码中是以哪种方式存储的。
找到zend/zend.h 418行:
struct _zend_class_entry {char type;char *name;/* 类名 */zend_uint name_length;/* 类名字符串长度 */struct _zend_class_entry *parent; /* 父类 */int refcount; /* 引用计数 */zend_bool constants_updated;zend_uint ce_flags;/* 类的访问控制 */ HashTable function_table;/*类的成员函数 */HashTable default_properties;/*类的默认属性 */HashTable properties_info;/*类的属性信息 如访问控制等 */HashTable default_static_members;/*静态成员列表 */HashTable *static_members;HashTable constants_table;/* 常量列表 */const struct _zend_function_entry *builtin_functions; union _zend_function *constructor;/*构造函数*/union _zend_function *destructor;/*析构函数*/union _zend_function *clone;/*克隆方法*/ /*魔术方法 */union _zend_function *__get;union _zend_function *__set;union _zend_function *__unset;union _zend_function *__isset;union _zend_function *__call;union _zend_function *__callstatic;union _zend_function *__tostring;union _zend_function *serialize_func;union _zend_function *unserialize_func; zend_class_iterator_funcs iterator_funcs; /* handlers */zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC);zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC); /* a class implements this interface */union _zend_function *(*get_static_method)(zend_class_entry *ce, char* method, int method_len TSRMLS_DC); /* serializer callbacks */int (*serialize)(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);int (*unserialize)(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC); zend_class_entry **interfaces;/*类实现的接口 */zend_uint num_interfaces;/*类实现的接口数 */ /*类所在文件信息 */char *filename;zend_uint line_start;zend_uint line_end;char *doc_comment;zend_uint doc_comment_len; struct _zend_module_entry *module;};
从PHP自带的SPL中,我们可以看到有类的继承,从这里出发,可以找到我们所需要的实现过程
从手册中选择CachingIterator类作为切入点。
CachingIterator extends IteratorIterator implements OuterIterator , Traversable , Iterator , ArrayAccess , Countable
跟踪过程如下:
//在ext/spl/spl_iterators.c 3246行,REGISTER_SPL_SUB_CLASS_EX(CachingIterator, IteratorIterator, spl_dual_it_new, spl_funcs_CachingIterator); // ext/spl/spl_functions.h 34行#define REGISTER_SPL_SUB_CLASS_EX(class_name, parent_class_name, obj_ctor, funcs) / spl_register_sub_class( spl_ce_ ## class_name, spl_ce_ ## parent_class_name, # class_name, obj_ctor, funcs TSRMLS_CC); // ext/spl/spl_functions.c 56行PHPAPI void spl_register_sub_class(zend_class_entry ** ppce, zend_class_entry * parent_ce, char * class_name, void *obj_ctor, const zend_function_entry * function_list TSRMLS_DC)*ppce = zend_register_internal_class_ex( ce, parent_ce, NULL TSRMLS_CC); // zend/zend_API.c 2196行ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC)zend_do_inheritance(register_class, parent_ce TSRMLS_CC); // zend/zend_compile.c 2784行 ZEND_API void zend_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); } /* final类不能继承 */ 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; /* 拷贝序列化和反序列化回调函数 */ if (!ce- serialize) { ce- serialize = parent_ce- serialize; if (!ce- unserialize) { ce- unserialize = parent_ce- unserialize; } /* 继承父类的接口 在此处有停下来思考,为何要这么做 */ zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC); /* 继承父类的属性 */ zend_hash_merge( ce- default_properties, parent_ce- default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0); if (parent_ce- type != ce- type) { /* 用户自定义的类从内部类继承 */ 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, (void (*)(void *)) zval_add_ref, 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; } else if (!(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); }}
关于上面do_inherit_parent_constructor(ce)
此方法实现魔术方法继承,如果子类中没有相关的魔术方法,则继承父类的对应方法。如下所示的PHP代码为子类没构造函数的情况
class Base {public function __construct() { echo Base __construct br / }} class Foo extends Base { } $foo = new Foo();
如上,会输出:Base __construct
显然继承了父类的构造方法,如果子类有自己的构造方法,并且需要调用父类的构造方法时,需要在子类的构造方法中调用父类的构造方法,PHP不会自动调用。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP !
相关推荐:
浅谈PHP源码二十七:PHP对构造方法的识别
浅谈PHP源码二十六:PHP快速排序源码实现的简化
浅谈PHP 源码二十五:关于next,current,key函数
以上就是浅谈PHP源码二十八:关于类结构和继承的详细内容,PHP教程
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
新闻热点
疑难解答