本篇文章的內容介紹的是關於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();這樣定義一個屬性就會觸發語法錯誤。
成員屬性又分為兩類:普通屬性、靜態屬性,與常量的儲存方式不同,成員屬性的初始化值並不是直接用以"屬性名稱"作為索引的雜湊表儲存的,而是通過數組儲存的
實際只是成員屬性的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)
成員方法也有靜態、非靜態之分,靜態方法中不能使用$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代碼的編譯