php對象底層結構,PHP 底層原理之類和對象

728bc4e497ae519719dc45b634ed8cd1.png

對于PHPer來說,OOP是不可或缺的開發思維,但是你對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;//類的類型,在編譯階段被區分是普通類,接口,抽象類

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_functions;// 方法定義入口

/* 魔術方法 */

//所有魔術方法單獨存放,初始化時被設置為null

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)

};

由上面代碼可以看出,類的成員變量、成員方法都是存放在各自的結構體中,而結構體的數據結構和之前講解的變量和函數的數據結構一模一樣,只不過編譯后的成員變量和成員方法是存放在類結構體中而已

對象的生成

我們都知道,對象是new出來的,但是從底層來看,對象生成分為3步

第一步:根據類名去全局類列表內查找該類是否存在,如果存在,則獲取存儲類的變量

第二步:判斷類是否是普通類(非抽象類或接口);如果是普通類則給需要創建的對象存放的zval容器分配內存,并設置容器類型為IS_OBJECT

第三步:執行對象初始化操作,將對象添加到全局對象列表(對象池)中

附上對象的數據結構:typedef struct _zend_object {

zend_class_entry *ce; //對象的類結構

HashTable *properties; //對象屬性

HashTable *guards; /* protects from __get/__set ... recursion */

} zend_object;

獲取和設置成員變量

獲取成員變量:

第一步,獲取對象的屬性,從對象的properties查找是否存在與名稱對應的屬性,如果存在返回結果,如果不存在,轉第二步

第二步,如果存在get魔術方法,則調用此方法獲取變量,如果不存在,則報錯

設置成員變量:

第一步,獲取對象的屬性,從對象的properties查找是否存在與名稱對應的屬性,如果存在且已有的值和需要設置的值相同,則不執行任何操作,否則執行變量賦值操作,如果不存在,轉第二步

第二步,如果存在_set魔術方法,則調用此方法設置變量,如果不存在,轉第三步

第三步,如果成員變量一直沒有被設置過,則直接將此變量添加到對象的properties字段所在HashTable中。

總結

到今天為止,我們差不多已經將關于php的底層原理講了一個遍了。當然,在這期間,不少同學跟我說,現在都已經逐漸開始使用php7了,你現在講解的內容還是php5,會不會過時了?其實我講解php5也是為講php7作準備,php7畢竟是php5的延展,了解了php5之后,再去了解php7會更加容易些。而且php也是從php5開始才逐漸完善起來的,我們有必要了解下php5的內容。不過從下周開始,我們會開始從底層比較php7和php5的不同,敬請期待~

更多PHP相關技術文章,請訪問PHP教程欄目進行學習!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/271032.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/271032.shtml
英文地址,請注明出處:http://en.pswp.cn/news/271032.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

程序默認在副屏顯示_聊一款性價比極高的電競顯示器

小米在6月17日開啟了小米顯示器27寸165Hz版本的眾籌,這臺顯示器的分辨率為2560x1440,也就是大家熟悉的小金剛,它與大金剛的最大區別也只是省去了G-Sync功能,而其他方面的參數幾乎是一致的。那么我們今天就來聊聊這款真香的顯示器。…

CocoaPods安裝和使用教程

CocoaPods是什么? 當你開發iOS應用時,會經常使用到很多第三方開源類庫,比如JSONKit,AFNetWorking等等。可能某個類庫又用到其他類庫,所以要使用它,必須得另外下載其他類庫,而其他類庫又用到其他…

事務管理基礎:兩段鎖協議、活鎖、死鎖相關知識整理

1、兩段鎖協議(Two-phase Locking Protocol) 兩段鎖協議是指對任何數據進行讀寫之前必須對數據進行加鎖;在釋放一個封鎖之后,事務不再申請和獲得任何其他封鎖。兩段鎖協議中兩段的含義:事務分為兩個階段,第…

php 空函數,PHP 中函數 isset(), empty(), is_null() 的區別

PHP 中函數 isset(), empty(), is_null() 的區別,使用 PHP 進行開發的時候,經常會用到 isset(), empty(), is_null() 這幾個函數對數據進行判斷,但是這是哪個函數的具體區別其實沒有很好的掌握。下面我們詳細講解一下:NULL什么是 NULL&#x…

UVa11021

11021 TribblesGRAVITATION, n.“The tendency of all bodies to approach one another with a strengthproportion to the quantity of matter they contain – the quantity ofmatter they contain being ascertained by the strength of their tendencyto approach one anot…

python合法變量類型_Python 變量類型

變量存儲在內存中的值。這就意味著在創建變量時會在內存中開辟一個空間。基于變量的數據類型,解釋器會分配指定內存,并決定什么數據可以被存儲在內存中。因此,變量可以指定不同的數據類型,這些變量可以存儲整數,小數或…

數據庫系統故障相關知識筆記

數據庫系統中可能發生的故障主要包括事務故障、系統故障、介質故障、計算機病毒等。下面給大家簡單整理一下相關的故障知識筆記。1、事務故障事務故障是因為程序執行錯誤而引起的非預期、異常終止的故障。主要有邏輯錯誤、系統錯誤導致事務的執行失敗。邏輯錯誤:比如…

dede php分頁代碼,DEDECMS系統分頁標簽自定義二次開發

以前有給大家寫過一篇自定義dedecms留言板的分頁,下面我再來給大家分享一篇自定義常見的分頁標簽例子,希望文章對大家會有所幫助.自定搜索結果頁面文章分頁,在/plus文件夾中新建一個search.php文件,代碼如下:require_once(dirname(__FILE__)."/../include/common.inc.php&…

windows下gvim中文亂碼解決方案

網羅了一些網上的解決windows下gvim中文亂碼的解決方案,都試了一遍,可惜都不能完全解決我的所有問題,最后我綜合一下網上的兩種方案,得到了最后完全解決我的中文亂碼問題的方案,配置很簡單,就是把下面的配置…

python主從_python—mariadb自動部署主從

import configparserimport osdef config_mariadb_yum():exists os.path.exists(/etc/yum.repos.d/mariadb.repo)if exists:print(mariadb.repo文件已經存在)yum_install_mariadb()else:config configparser.ConfigParser()config.read(/etc/yum.repos.d/mariadb.repo, encod…

數據庫系備份相關知識筆記

1、數據庫備份的知識介紹在互聯網時代,最珍貴的財產不是計算機應用軟件,更不是計算機硬件,而是企業在業務長期發展過程中積累下來的業務數據。建立網絡最根本的用途是更加方便的傳遞、使用數據,人為原因、硬盤損壞、計算機病毒、斷…

python數組合并、輸入三行數據,如何在python中合并兩個或三個3D數組?

Numpy的hstack、vstack或dstack(取決于要連接數組的軸)將連接多維數組。在請注意,對于MODIS氣溶膠數據,使用hstack連接陣列有時會拋出錯誤,因為有時陣列是203 x 135,有時是204 x 135,因此水平維度并不總是匹配的基于您…

操作系統:分享6 個“嚇人”的 Linux 命令

目錄 1、crypt 2、kill 3、shred 5、at midnight 6、daemons 1、crypt 好吧,我們一直都有crypt。顧名思義,crypt不是存放垃圾文件的地宮或墓坑,而是加密文件內容的命令。 如今,“crypt”通常作為一個腳本而實現:通過調…

谷歌網絡代理工具_谷歌更新了Dialogflow AI引擎,幫助客戶創建更好的虛擬代理...

日前,谷歌發布了對其Dialogflow的一些重要更新,對話流是其呼叫中心人工智能服務的主要技術,它可以自動與呼叫中心的客戶進行交互。據悉,Dialogflow是一個會話人工智能引擎,用于創建虛擬代理,可以理解和響應…

php use閉包參數,php 閉包use的使用

閉包可以從父作用域中繼承變量。 任何此類變量都應該用 use 語言結構傳遞進去。PHP的閉包即為匿名函數。示例如下。$message hello;// 繼承 $message$example function () use ($message) {var_dump($message);};echo $example(); //hello// Inherited variables value is fr…

數據庫恢復相關知識筆記

1、數據庫恢復的原理數據庫恢復的原理主要是在數據庫發生故障之后,建立冗余數據,在故障發生之后利用冗余數據來完成數據庫恢復。數據轉儲和建立日志文件是建立冗余數據常用的技術手段。一般情況下兩種技術手段會同時使用。2、故障恢復的兩個操作故障恢復…

C++ map注意事項

C map注意事項 1、在map中,由key查找value時,首先要判斷map中是否包含key。 2、如果不檢查,直接返回map[key],可能會出現意想不到的行為。如果map包含key,沒有問題,如果map不包含key,使用下標有…

oracle數據庫any,Oracle權限集合全集

alter any cluster 修改任意簇的權限alter any index 修改任意索引的權限alter any role 修改任意角色的權限alter any sequence 修改任意序列的權限alter any snapshot 修改任意快照的權限alter any table 修改任意表的權限alter any trigger 修改任意觸發器的權限alter clust…