PHP核心--類和物件導向____PHP

來源:互聯網
上載者:User
在最開始接觸PHP的時候,都是面向過程的方法來自己做一些很簡單的網站在玩,寫PHP代碼就是堆砌,拓展性與維護性太差改個邏輯極不方便。後來發現PHP是支援物件導向的,忽然覺得自己那是後還真是年輕,真是孤陋寡聞呀,畢竟PHP是用C來實現,也不足為奇。 前言: 從我們接觸 PHP 開始,我們最先遇到的是函數:數組操作函數,字串操作函數,檔案操作函數等等。 這些函數是我們使用PHP的基礎,也是PHP自出生就支援的面向過程編程。面向過程將一個個功能封裝, 以一種模組化的思想解決問題。 從PHP4起開始支援物件導向編程。但PHP4的物件導向支援不太完善。 從PHP5起,PHP引入了新的物件模型(Object Model),增加了許多新特性,包括存取控制、 抽象類別和final類、類方法、魔術方法、介面、對象複製和類型提示等。 並且在近期發布的PHP5.3版本中,針對物件導向編程增加了命名空間、延遲靜態繫結 以及增加了兩個魔術方法__callStatic()和__invoke()。 那麼,在PHP底層,其是怎麼實現的呢,其結構如何。 一。類的結構 引用TIPI的一個案例:
class ParentClass {} interface Ifce {        public function iMethod();} final class Tipi extends ParentClass implements Ifce {        public static $sa = 'aaa';        const CA = 'bbb';         public function __constrct() {        }         public function iMethod() {        }         private function _access() {        }         public static function access() {        }}
這裡定義了一個父類ParentClass,一個介面Ifce,一個子類Tipi。子類繼承父類ParentClass, 實現介面Ifce,並且有一個靜態變數$sa,一個類常量 CA,一個公用方法,一個私人方法和一個公用靜態方法。 這些結構在Zend引擎內部是如何?的。類的方法、成員變數是如何儲存的。存取控制,靜態成員是如何標記的。 首先,我們看看類的內部儲存結構:
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_IMPLICIT_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_functions;// 方法定義入口      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)};
取上面這個結構的部分欄位,我們分析文章最開始的那段PHP代碼在核心中的表現。 如下 所示:
欄位名 欄位說明 ParentClass類 Ifce介面 Tipi類
name 類名 ParentClass Ifce Tipi
type 類別 2(使用者自訂) 2 (使用者自訂) 2 (使用者自訂,1為系統內建類)
parent 父類 空 空 ParentClass類
refcount 引用計數 1 1 2
ce_flags 類的類型 0 144 524352
function_table 函數列表 空 function_name=iMethod | type=2 | fn_flags=258 function_name=__construct | type=2 | fn_flags=8448
function_name=iMethod | type=2 | fn_flags=65800
function_name=_access | type=2 | fn_flags=66560
function_name=access | type=2 | fn_flags=257
interfaces 介面列表 空 空 Ifce介面 介面數為1
filename 存放檔案地址 /tipi.php /tipi.php /ipi.php
line_start 類開始行數 15 18 22
line_end 類結束行數 16 20 38

二。變數與成員變數 如 PHP核心的儲存機制(分離/改變)所介紹, 變數要麼是定義在全域範圍中,叫做全域變數,要麼是定義在某個函數中, 叫做局部變數。 成員變數是定義在類裡面,並和成員方法處於同一層次。如下一個簡單的PHP程式碼範例,定義了一個類, 並且這個類有一個成員變數。
class Tipi { public $var;}
1.成員變數的訪問: 訪問這個成員變數當然是通過對象來訪問。 2.成員變數的規則: 1.介面中不允許使用成員變數 2.成員變數不能擁有抽象屬性 3.不能聲明成員變數為final 4.不能重複聲明屬性 在聲明類的時候初始化了類的成員變數所在的HashTable,之後如果有新的成員變數聲明時,在編譯時間zend_do_declare_property。函數首先檢查成員變數不允許的這4 條情況。 比如:.
class Tipi { public final $var;}
運行程式將報錯,違反了第三條:Fatal error: Cannot declare property Tipi::$var final, the final modifier is allowed only for methods and classes in .. 這個錯誤由zend_do_declare_property函數拋出
三。函數與成員方法 成員方法從本質上來講也是一種函數,所以其儲存結構也和常規函數一樣,儲存在zend_function結構體中。
對於一個類的多個成員方法,它是以HashTable的資料結構儲存了多個zend_function結構體。 和前面的成員變數一樣,在類聲明時成員方法也通過調用zend_initialize_class_data方法,初始化了整個方法列表所在的HashTable。 在類中我們如果要定義一個成員方法,格式如下:
class Tipi{      public function t() {echo 1; }}
除去存取控制關鍵字,一個成員方法和常規函數是一樣的,從文法解析中調用的函數一樣(都是zend_do_begin_function_declaration函數), 但是其調用的參數有一些不同,第三個參數is_method,成員方法的賦值為1,表示它作為成員方法的屬性。 在這個函數中會有一系統的編譯判斷,比如 在介面中不能聲明私人的成員方法 。 看這樣一段代碼:
interface Ifce {     private function method();}
如果直接運行,程式會報錯:Fatal error: Access type for interface method Ifce::method() must be omitted in 這段代碼對應到zend_do_begin_function_declaration函數中的代碼。 四。方法(Function)與函數(Method)的異同 在前面介紹了函數的實現,函數與方法的本質是比較相似的,都是將一系列的邏輯放到一個集合裡執行, 但二者在使用中也存在很多的不同,這裡我們討論一下二者的實現。 從實現的角度來看,二者內部代碼都被最終解釋為op_array,其執行是沒有區別的(除非使用了$this/self等對象特有的變法或方法), 而二者的不同體現在兩個方面: 1.是定義(註冊)的實現; 2.是調用的實現; 定義(註冊)方式的實現 函數和方法都是在編譯階段註冊到compiler_globals變數中的,二者都使用相同的核心處理函數zend_do_begin_function_declaration() 和zend_do_end_function_declaration()來完成這一過程。 二者的內部內容會被最終解釋並儲存為一個op_codes數組,但編譯後“掛載”的位置不同,如下圖:
 PHP中函數與方法的註冊位置
調用方式的實現
定義位置的不同,以及性質的不同,決定了方法比函數要進行更多的驗證工作, 方法的調用比函數的調用多一個名為ZEND_INIT_METHOD_CALL的OPCODE,  其作用是把方法註冊到execute_data.fbc , 然後就可以使用與函數相同的處理函數 ZEND_DO_FCALL_BY_NAME進行處理。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.