PHP内部类是怎么实现的?它的内存布局及存储是怎么样的呢?继承、封装、多态又是怎么实现的呢?
类的结构
首先看一下类的内部存储结构:
struct _zend_class_entry{
char type;// 类型: ZEND_INTERNAL_CLASS / ZEND_USER_CLASS
char *name;//类名称
zend_uint name_length;// 即 sizeof(name) - 1
struct _zend_class_entry *parent;//继承的父类
int refcount;//引用类
zend_bool constants_updated;
zend_uint ce_flags;// ZEND_ACC_IMLICIT_ABSTRACT_CLASS 类存在abstract 方法
// ZEND_ACC_EXPLICIT_ABSTRACT_CLASS: 在类名称前加了 abstract 关键字
// ZEND_ACC_FINAL_CLASS
// ZEND_ACC_INTERFACE
HashTable function_table;//方法
HashTable default_properties;// 默认属性
HashTable properties_info;//属性信息
HashTable default_static_members;// 类本身所具有的静态变量
HashTable *static_members;// type = ZEND_USER_CLASS时, 取&default_static_members;
// type == ZEND_INTERAL_CLASS时, 设为 NULL
HashTable constants_table;//常量
struct _zend_function_entry *builtin_functinons;//方法定义入口
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 *__tostring;
union _zend_function *serialize_func;
union _zend_function *unserialize_func;
zend_class_iterator_funcs iterator_funcs;//迭代
// 类句柄
zend_object_value(*create_object)(zend_class_entry *class_type TSRMLS_DC);
zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, intby_ref TSRMLS_DC);
/* 类声明的接口 */
int(*interface_gets_implemented)(zend_class_entry *iface,
zend_class_entry *class_type TSRMLS_DC);
/* 序列化回调函数指针 */
int(*serialize)(zval *object, unsignedchar**buffer, zend_uint *buf_len,
zend_serialize_data *data TSRMLS_DC);
int(*unserialize)(zval **object, zend_class_entry *ce, constunsignedchar*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; // 类所在的模块入口:EG(current_module)
}
类的实现
在语法分析阶段将类分为三种类型:常规类(T_CLASS),抽象类(T_ABSTRACT T_CLASS)和final类(T_FINAL T_CLASS )。 他们分别对应的类型在内核中为:
- 常规类(T_CLASS) 对应的type=0
- 抽象类(T_ABSTRACT T_CLASS) 对应type=ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
- final类(T_FINAL T_CLASS) 对应type=ZEND_ACC_FINAL_CLASS
除了上面的三种类型外,类还包含有另外两种类型没有加abstract关键字的抽象类和接口:
- 没有加abstract关键字的抽象类,它对应的type=ZEND_ACC_IMPLICIT_ABSTRACT_CLASS。由于在class前面没有abstract关键字,在语法分析时并没有分析出来这是一个抽象类,但是由于类中拥有抽象方法,在函数注册时判断成员函数是抽象方法或继承类中的成员方法是抽象方法时,会将这个类设置为此种抽象类类型。
- 接口,其type=ZEND_ACC_INTERFACE。接口类型的区分是在interface关键字解析时设置,见interface_entry:对应的语法说明。