原創:PHP核心研究之類的成員屬性與方法
這篇要詳細講講PHP類的成員屬性及方法.
上一篇中曾經介紹到zend_do_begin_class_declaration這個函數,它用來創建並初始化一個zend_class_entry
類的所有信息都保存在這個結構中,那麼屬性以及方法是怎麼保存的呢?
1
2
3
class{
還記得上一篇說過的zend_initialize_class_data函數嗎?不記得也沒關係.我們仔細來瞧瞧這個函數zend_initialize_class_data(new_class_entry, 1
7
8
2021222324 252627282930313 37383940 4142434445464748
3
54
55
56
57
58
59
60
61
62
ZEND_APIvoidzend_initialize_class_data(fre_class
{
zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ce->refcount = 1;
ce->constants_updated = 0;
;
ce->doc_comment = NULL;
_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_in
zend_ properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes,) 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0); zend_hash_init_ex(&ce->constants_table, 0 , NULL, zval_ptr_dtor_func, persistent_hashes, 0); zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_F1,D,o);if(ce->type == ZEND_INTERNAL_CLASS) {
#ifdef ZTS
intn = zend_hash_num_elements(CG(class_table));
embers) && n >= CG(last_static_member)) { CG(last_static_member) = n+1; CG(static_members) =realreal88,00m CG(static_members) =realreal8(H未來)> CG(static_members)[n] = NULL; } ce->static_members = (HashTable*)(zend_intptr_t)n; static_members = NULL;#endif }else{ ; }? NULL;
ce->__get = NULL; ce- >__set = NULL; ce->__unset = NULL; ce->__isset = NULL; ce->__call = NULL;ce ->__callstatic = NULL;
ce->__tostring = NULL;
ce-> ce ce->interface_gets_implemented = NULL;
ce->get_static_method = NULL;
ce 0;
ce->interfaces = NULL ;
ce->ser ialize = NULL;
ce->unserialize = NULL ;
ce->uns erialize_func = NULL;
}
zend_bool permanent_hashes = (ce->type = = ZEND_INTERNAL_CLASS)? 1 : 0;
普通用戶類別與內部類別分配記憶體的方式不同….為什麼還有差別呢? - >default_properties, 0, NULL, zval_ptr_dtor_func, permanent_hashes, 0);zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, perman_members, p. 0, NULL , ptr_dtor_func,persist_hashes, 0);
zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, permanent_hashes, 0);如果你看過這篇文章,那麼你肯定知道這是在初始化HashTable。是這樣,
default_properties,default_static_members等都是HashTable類型的指標.所以初始化當然要zend_hash_init了.第36-61行初始化魔術方法
不過這裡只是初始化哦..好像並沒有設定屬性.$name屬性是如何加到屬性表裡的呢??? 1234567
5
6
12
13
14
15
16
17
18
19
20
2021119
20
23211 526 unticked_class_declaration_statement: T_STRING自延伸
{ zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); }
implements_list
'{'
class_statement_list
'}'{ zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); }
| interface_entry T_STRING
{且如 N5, N$19 }
interface_extends_list
'}'{ zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); };class_statement: variable_modifiers { CG(access_type) = Z_LVALstant.u. } class_variable_declaration';' | class_constant_declaration';' | method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); }'(' parameter_list')'method_body { zend_do_abstract_method(&$4)$ zend_do_end_function_declaration(&$2 TSRMLS_CC); };class_variable_declaration: { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } | class_variable_declaration','T_VARIABLE'='static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } | T_VARIABLE type) TSRMLS_CC); } | T_VARIABLE'='static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); }; 這個還記得吧?類初始化成功後類別裡面的東西當然要執行class_statement_list這個啦..^.^
類體裡會呼叫🜎2
3
4
5
6
7
8
9
10
15161718 192021222324250 31323334 3536373839
40
41
42
43
44 TSRMLS_DC)/* {{ { */
{
zval *屬性;
zend_property_info *existing_property_info;
char*comment = NULL;
if(CG(active_class_entry) ->ce_flags & ZEND_ACC_INTERFACE) {
變項");
}
zend_error(E_COMPILE_ERROR,"屬性不能宣告為抽象");
}
_ (E_COMPILE_ERROR,"無法宣告屬性%s::$%s Final,final 修飾詞只適用於方法與類別",
CG(active_class_entry)->name, var_name->u.constant.value。 ;
}
if(zend_hash_find(&CG(active_class_entry)-prodm-mR. ue.str .len+1, (void **) &existing_property_info)==SUCCESS) {
if(!(existing_property_info- zend_error (E_COMPILE_ERROR,"無法重新宣告%s::$%s" , CG(active_class_entry)-> name, var_name->u.constant.value.str.val);
}
;if(值) { }else{ Z_TYPE_P(屬性) = IS_NULL; } 評論= CG(doc_comment); comment_len = CG (doc_comment_len); CG(doc_comment) = NULL; } zend_declare_property_ex(CG(active_class_entry), var_name->; u.str. var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC); efree(var_name->u.constant.value.
第8-25行:
如果你的類別宣告的是介面.那麼該介面是不能有屬性的會拋出Interfaces may not include member variables
如果類別的屬性被設定為abstract,那麼就會拋出Properties cannot be declared abstract
如果類別的屬性被設定為final,那麼會拋出Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes
一切沒有問題,會分配一個zval的資料,
如果屬性有初始值,那麼該資料會分配給zval,如果沒有,則呼叫INIT_PZVAL初始化zval,並設定類型為IS_NULL;
最後會呼叫zend_declare_property_ex將該zval加入指定的active_class_entry中
類的方法
類的方法
類的方法類的方法
類的方法類的方法
類的方法類的方法
類的方法類的方法
類的方法類
12345 class echo1; }
}
?是怎麼處理的?
先看規則 12345 variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration';' | class_constant_declaration';'ING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); }'('
{ zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
gin
熟嗎?
如果看過之前的文章,肯定眼熟
如果沒有看過.先去看看這篇文章. 函數的定義
這裡就不詳細講了.
只說說在那篇沒提到的內容
在這個函數中有一個判斷
1
2
3
4
5
6
17
5
6
1 if(is_method) { if(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) { ZEND_ACC_PUBLIC))) { s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val); Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT;/* propagates to the rest of the parser */ } _znode->u.constant);/* must be done *after* the above check */ }else{ fn_flags = 0; } 很明顯,如果是方法,那麼就會進去處理3-5行會拋出Access type for interface method %s::%s() must be omitted然後會呼叫
if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, size(arrazend, conofzend) void **) &CG(active_op_array)) == FAILURE) {zend_error(E_COMPILE_ERROR, “Cannot redeclare %s::%s()”, CG(active_class_entry)->name, name);
}直接把方法加到方法上到function_table裡.
下面會根據不同的類別聲明做不同的判斷. 以上就是原創:PHP核心研究之類的成員屬性與方法的內容,更多相關內容請關注PHP中文網(www.php.cn)!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

微信是主流的聊天工具之一,我們可以透過微信認識新的朋友,聯絡老的朋友,維繫朋友之間的友誼。正如天下沒有不散的宴席,人與人之間的相處難免會發生意見不合的時候。當一個人極度影響你的情緒,或是在相處的時候發現三觀不合,沒辦法再繼續溝通,那麼我們可能需要刪除微信好友的方法。怎麼刪除微信好友?刪除微信好友的方法第一步:在微信主介面輕觸【通訊錄】;第二步:點選對應要刪除的好友,進入【詳細資料】;第三步:點選右上角【...】;第四步:點選下方【刪除】即可;第五步:了解後頁面提示後,點選【刪除聯絡人】即可;溫馨

番茄小說是一款非常熱門的小說閱讀軟體,我們在番茄小說中經常會有新的小說和漫畫可以去閱讀,每一本小說和漫畫都很有意思,很多小伙伴也想著要去寫小說來賺取賺取零用錢,在把自己想要寫的小說內容編輯成文字,那麼我們要怎麼樣在這裡面去寫小說呢?小伙伴們都不知道,那就讓我們一起到本站本站中花點時間來看寫小說的方法介紹。分享番茄小說寫小說方法教學 1、先在手機上打開番茄免費小說app,點擊個人中心——作家中心 2、跳到番茄作家助手頁面——點擊創建新書在小說的結

七彩虹主機板在中國國內市場享有較高的知名度和市場佔有率,但是有些七彩虹主機板的用戶還不清楚怎麼進入bios進行設定呢?針對這一情況,小編專門為大家帶來了兩種進入七彩虹主機板bios的方法,快來試試吧!方法一:使用u盤啟動快捷鍵直接進入u盤裝系統七彩虹主機板一鍵啟動u盤的快捷鍵是ESC或F11,首先使用黑鯊裝機大師製作一個黑鯊U盤啟動盤,然後開啟電腦,當看到開機畫面的時候,連續按下鍵盤上的ESC或F11鍵以後將會進入到一個啟動項順序選擇的窗口,將遊標移到顯示“USB”的地方,然

而後悔莫及、人們常常會因為一些原因不小心刪除某些聯絡人、微信作為一款廣泛使用的社群軟體。幫助用戶解決這個問題,本文將介紹如何透過簡單的方法找回被刪除的聯絡人。 1.了解微信聯絡人刪除機制這為我們找回被刪除的聯絡人提供了可能性、微信中的聯絡人刪除機制是將其從通訊錄中移除,但並未完全刪除。 2.使用微信內建「通訊錄恢復」功能微信提供了「通訊錄恢復」節省時間和精力,使用者可以透過此功能快速找回先前刪除的聯絡人,功能。 3.進入微信設定頁面點選右下角,開啟微信應用程式「我」再點選右上角設定圖示、進入設定頁面,,

Win11管理員權限取得方法匯總在Windows11作業系統中,管理員權限是非常重要的權限之一,可以讓使用者對系統進行各種操作。有時候,我們可能需要取得管理員權限來完成一些操作,例如安裝軟體、修改系統設定等。下面就為大家總結了一些取得Win11管理員權限的方法,希望能幫助大家。 1.使用快捷鍵在Windows11系統中,可以透過快捷鍵的方式快速開啟命令提

手機遊戲成為了人們生活中不可或缺的一部分,隨著科技的發展。它以其可愛的龍蛋形象和有趣的孵化過程吸引了眾多玩家的關注,而其中一款備受矚目的遊戲就是手機版龍蛋。幫助玩家們在遊戲中更好地培養和成長自己的小龍,本文將向大家介紹手機版龍蛋的孵化方法。 1.選擇合適的龍蛋種類玩家需要仔細選擇自己喜歡並且適合自己的龍蛋種類,根據遊戲中提供的不同種類的龍蛋屬性和能力。 2.提升孵化機的等級玩家需要透過完成任務和收集道具來提升孵化機的等級,孵化機的等級決定了孵化速度和孵化成功率。 3.收集孵化所需的資源玩家需要在遊戲中

字體大小的設定成為了重要的個人化需求,隨著手機成為人們日常生活的重要工具。以滿足不同使用者的需求、本文將介紹如何透過簡單的操作,提升手機使用體驗,調整手機字體大小。為什麼需要調整手機字體大小-調整字體大小可以使文字更清晰易讀-適合不同年齡段用戶的閱讀需求-方便視力不佳的用戶使用手機系統自帶字體大小設置功能-如何進入系統設置界面-在在設定介面中找到並進入"顯示"選項-找到"字體大小"選項並進行調整第三方應用調整字體大小-下載並安裝支援字體大小調整的應用程式-開啟應用程式並進入相關設定介面-根據個人

Oracle版本查詢方法詳解Oracle是目前世界上最受歡迎的關聯式資料庫管理系統之一,它提供了豐富的功能和強大的效能,廣泛應用於企業。在進行資料庫管理和開發過程中,了解Oracle資料庫的版本是非常重要的。本文將詳細介紹如何查詢Oracle資料庫的版本信息,並給出具體的程式碼範例。查詢資料庫版本的SQL語句在Oracle資料庫中,可以透過執行簡單的SQL語句
