PHP7核心剖析8之 類

來源:互聯網
上載者:User
本篇文章的內容介紹的是關於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代碼的編譯

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.