对象

对象是类的实例,PHP中要创建一个类的实例,必须使用 new 关键字。类应在被实例化之前定义(某些情况下则必须这样,比如最后那几个例子)。

3.4.2.1 对象的数据结构

对象的数据结构非常简单:

typedef struct _zend_object     zend_object;

struct _zend_object {
    zend_refcounted_h gc; //引用计数
    uint32_t          handle;
    zend_class_entry *ce; //所属类
    const zend_object_handlers *handlers; //对象操作处理函数
    HashTable        *properties;
    zval              properties_table[1]; //普通属性值数组
};

几个主要的成员:

(1)handle: 一次request期间对象的编号,每个对象都有一个唯一的编号,与创建先后顺序有关,主要在垃圾回收时用,下面会详细说明。

(2)ce: 所属类的zend_class_entry。

(3)handlers: 这个保存的对象相关操作的一些函数指针,比如成员属性的读写、成员方法的获取、对象的销毁/克隆等等,这些操作接口都有默认的函数。

struct _zend_object_handlers {
    int                                     offset;
    zend_object_free_obj_t                  free_obj; //释放对象
    zend_object_dtor_obj_t                  dtor_obj; //销毁对象
    zend_object_clone_obj_t                 clone_obj;//复制对象

    zend_object_read_property_t             read_property; //读取成员属性
    zend_object_write_property_t            write_property;//修改成员属性
    ...
}

//默认值处理handler
ZEND_API zend_object_handlers std_object_handlers = {
    0,
    zend_object_std_dtor,                   /* free_obj */
    zend_objects_destroy_object,            /* dtor_obj */
    zend_objects_clone_obj,                 /* clone_obj */
    zend_std_read_property,                 /* read_property */
    zend_std_write_property,                /* write_property */
    zend_std_read_dimension,                /* read_dimension */
    zend_std_write_dimension,               /* write_dimension */
    zend_std_get_property_ptr_ptr,          /* get_property_ptr_ptr */
    NULL,                                   /* get */
    NULL,                                   /* set */
    zend_std_has_property,                  /* has_property */
    zend_std_unset_property,                /* unset_property */
    zend_std_has_dimension,                 /* has_dimension */
    zend_std_unset_dimension,               /* unset_dimension */
    zend_std_get_properties,                /* get_properties */
    zend_std_get_method,                    /* get_method */
    NULL,                                   /* call_method */
    zend_std_get_constructor,               /* get_constructor */
    zend_std_object_get_class_name,         /* get_class_name */
    zend_std_compare_objects,               /* compare_objects */
    zend_std_cast_object_tostring,          /* cast_object */
    NULL,                                   /* count_elements */
    zend_std_get_debug_info,                /* get_debug_info */
    zend_std_get_closure,                   /* get_closure */
    zend_std_get_gc,                        /* get_gc */
    NULL,                                   /* do_operation */
    NULL,                                   /* compare */
}

> Note: 这些handler用于操作对象(如:设置、读取属性),std_object_handlers是PHP定义的默认、标准的处理函数,在扩展中可以自定义handler,比如:重定义write_property,这样设置一个对象的属性时将调用扩展自己定义的处理函数,让扩展拥有了更高的控制权限。 > > 需要注意的是:const zend_object_handlers *handlers,这里的handlers指针加了const修饰符,const修饰的是handlers指向的对象,而不是handlers指针本身,所以扩展中可以将一个对象的handlers修改为另一个zend_object_handlers指针,但无法修改zend_object_handlers中的值,比如:obj->handlers->write_property = xxx将报错,而:obj->handlers = xxx则是可以的。

(4)properties: 普通成员属性哈希表,对象创建之初这个值为NULL,主要是在动态定义属性时会用到,与properties_table有一定关系,下一节我们将单独说明,这里暂时忽略。

__(5)properties_table:__ 成员属性数组,还记得我们在介绍类一节时提过非静态属性存储在对象结构中吗?就是这个properties_table!注意,它是一个数组,zend_object是个变长结构体,分配时会根据非静态属性的数量确定其大小。

联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2024

备案号:京ICP备15003423号-3