首頁  >  文章  >  後端開發  >  PHP7核心剖析8之 類

PHP7核心剖析8之 類

不言
不言原創
2018-04-13 15:14:411551瀏覽

這篇文章的內容介紹的是關於PHP7核心剖析8之類  ,現在分享給大家,有需要的朋友可以參考一下

1.類別的結構

類別是編譯階段的產物,編譯完成後我們定義的每個類別都會產生一個zend_class_entry,它保存著類別的全部信息,在執行階段所有類別相關的操作都是用的這個結構
struct _zend_class_entry {
    char type;          //类的类型:内部类ZEND_INTERNAL_CLASS(1)、用户自定义类ZEND_USER_CLASS(2)
    zend_string *name;  //类名,PHP类不区分大小写,统一为小写
    struct _zend_class_entry *parent; //父类
    int refcount;
    uint32_t ce_flags;  //类掩码,如普通类、抽象类、接口,

    int default_properties_count;        //普通属性数,包括public、private
    int default_static_members_count;    //静态属性数,static
    zval *default_properties_table;      //普通属性值数组
    zval *default_static_members_table;  //静态属性值数组
    zval *static_members_table;
    HashTable function_table;  //成员方法哈希表
    HashTable properties_info; //成员属性基本信息哈希表,key为成员名,value为zend_property_info
    HashTable constants_table; //常量哈希表,通过constant定义的

    //以下是构造函授、析构函数、魔术方法的指针
    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 *__debugInfo;
    union _zend_function *serialize_func;
    union _zend_function *unserialize_func;
}


2.類別常數

PHP中可以把在類別中始終保持不變的值定義為常數,在定義和使用常數的時候不需要使用$ 符號,常數的值必須是一個定值,它們透過zend_class_entry.constants_table進行存儲,這是一個哈希結構
常量的读取:

class my_class {
    const A1 = "hi";
}
echo my_class::A1;

编译到echo my_class::A1这行时首先会尝试检索下是否已经编译了my_class,如果能在CG(class_table)中找到,则进一步从类的contants_table查找对应的常量,找到的话则会复制其value替换常量,简单的讲就是类似C语言中的宏,编译时替换为实际的值了,而不是在运行时再去检索。

echo my_class::A1;

class my_class {
    const A1 = "hi";
}

在运行时再去检索。替换成为实际的值


#3.成員屬性

屬性中的變數可以初始化,但是初始化的值必須是常數,這裡的常數是指PHP腳本在編譯階段時就可以得到其值,而不依賴執行時的資訊才能求值,例如public $time = time();這樣定義一個屬性就會觸發語法錯誤。

成員屬性又分為兩類:普通屬性、靜態屬性,與常數的存儲方式不同,成員屬性的初始化值並不是直接用以"屬性名"作為索引的哈希表存儲的,而是透過陣列保存的

PHP7核心剖析8之 類

實際上只是成員屬性的VALUE透過陣列儲存的,存取時仍然是根據以"屬性名"為索引的散列表查找具體VALUE的,而這個散列表是zend_class_entry.properties_info
typedef struct _zend_property_info {
    uint32_t offset; //普通成员变量的内存偏移值,静态成员变量的数组索引
    uint32_t flags;  //属性掩码,如public、private、protected及是否为静态属性
    zend_string *name; //属性名:并不是原始属性名,private会在原始属性名前加上类名,protected则会加上*作为前缀
    zend_string *doc_comment;
    zend_class_entry *ce; //所属类
} zend_property_info;


4.成員方法

#每個類別可以定義若干屬於本類別的函數(稱之為成員方法),這種函數與普通的function相同,只是以類別的維度進行管理,不是全局性的,所以成員方法保存在類別中而不是EG( function_table)

PHP7核心剖析8之 類

成員方法也有靜態、非靜態之分,靜態方法中不能使用$this,因為其操作的作用域全部都是類別的而不是物件的,而非靜態方法中可以透過$this存取屬於本物件的成員屬性


5.物件的資料結構

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]; //普通属性值数组
};
物件的建立:首先是根據類別名稱在EG(class_table)中尋找對應zend_class_entry、然後是建立並初始化一個物件、最後是初始化呼叫建構子的zend_execute_data

相關推薦:

PHP7核心剖析7之Zend引擎執行過程

PHP7核心剖析6之函數

########################################################## ##PHP7核心剖析5之PHP程式碼的編譯######

以上是PHP7核心剖析8之 類的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn