A brief discussion on PHP source code twenty-eight: About class structure and inheritance

不言
Release: 2023-04-02 06:28:01
Original
1817 people have browsed it

This article mainly introduces the twenty-eight words about PHP source code: Regarding class structure and inheritance, it has certain reference value. Now I share it with you. Friends in need can refer to it.

Brief Talk PHP source code twenty-eight: About class structure and inheritance

As a very critical and very tangled feature in object-oriented, we need to understand something
In PHP5, the concept of inheritance has been there from the beginning , today we start from the PHP source code to understand how it is implemented.
Before understanding class inheritance, we need to know how classes are stored in PHP source code.
Find line 418 of zend/zend.h:

 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;};
Copy after login

From the SPL that comes with PHP, we can see the inheritance of classes. From here, we can find the implementation process we need

Select the CachingIterator class from the manual as the entry point.
CachingIterator extends IteratorIterator implements OuterIterator, Traversable, Iterator, ArrayAccess, Countable
The tracking process is as follows:

 //在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);
    }}
Copy after login

About the above do_inherit_parent_constructor(ce)

This method implements magic method inheritance, if If there is no relevant magic method in the subclass, the corresponding method of the parent class will be inherited. The PHP code shown below is the case when the subclass has no constructor

class Base {
public function __construct() {
    echo &#39;Base __construct<br />&#39;;
}} class Foo extends Base { } $foo = new Foo();
Copy after login

As above, it will output: Base __construct
Obviously inherits the construction method of the parent class. If the subclass has its own construction method, and When you need to call the constructor of the parent class, you need to call the constructor of the parent class in the constructor of the subclass. PHP will not call it automatically.

The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!

Related recommendations:

A brief discussion on PHP source code twenty-seven: PHP’s identification of construction methods

A brief discussion on PHP Source code twenty-six: Simplification of PHP quick sort source code implementation

A brief discussion of PHP source code twenty-five: About next, current, key functions

The above is the detailed content of A brief discussion on PHP source code twenty-eight: About class structure and inheritance. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template