首先說下靜態變量和全局變量的區別,全局變量可以被所有函數訪問,如果多個獨立的函數使用了同名的變量,就會導致沖突,在只有一個函數需要訪問某個變量時,我們應該優先使用靜態變量,而不是全局變量
類中的靜態成員,它屬於整個類而不是屬於類的某個實例,靜態成員只保留一個變量值,而這個變量值對所有的實例都是有效的,所有的實例共享這個成員。
$this表示類的當前實例,Self::表示的是類本身 在類之外的代碼不能使用這個操作符,而且它也不能識別自己在繼承樹層次結構中的位置。也就是說在擴展類中使用self作用域時,self可以調用基類中聲明的方法,但他調用的總是已經在擴展類中重寫的方法。基類方法被重寫,但是如果要調用基類的方法,需要用到parent關鍵字。
靜態成員也可以只屬於父類,父子類中都定義了某個成員,需要使用parent來訪問父類中的靜態成員。這種情況下父子類中保存的靜態成員值不同。
使用靜態方式調用類中的方法,可以省略實例化類的代碼,並且還會更高效(省去實例化類時需要消耗的一小部分資源)
詞法語法分析流程
1 在文件Zend/zend_compile.c裡,詞法分析之後加上兩行代碼,用來打印出具體的詞法分析出來的分詞
retval = lex_scan(&zendlval->u.constant TSRMLS_CC); //原先的詞法分析腳本
if(zendlval->u.constant.value.lval && zendlval->u.constant.value.lval< 10000)
printf("word: %ld\n", zendlval->u.constant.value.lval);
else if(zendlval->u.constant.value.str.val)
printf("word: %s\n", zendlval->u.constant.value.str.val);
2在詞法分析zend_language_scanner.c中打印出詞法鏈接的case條件,方便後續跟蹤
printf("word-line:%d\n", yy_act);
switch ( yy_act )
3 在語法分析zend_language_parser.c中打印出語法鏈接的case條件,方便後續跟蹤
YY_REDUCE_PRINT(yyn);
printf("grammar-line: %d\n", yyn);
switch(yyn)
4 構造包含static的類文件
<?php
class classname{
public static $valname = 'test';
public $val = 'test1';
function functionname(){
echo self::$valname;
}
}
$obj = new classname();
echo $obj->functionname();
5 重要片段分析
word: classname
grammar-line: 93
grammar-line: 86
走了zend_do_begin_class_declaration
初始化類的信息
並且把類注冊進入了CG(class_table)
將當前類設置為CG(active_class_entry)
最後取出了下個操作碼進行了設置
grammar-line: 98
grammar-line: 168
public
grammar-line: 183
grammar-line: 181
word: static
grammar-line: 186
Z_LVAL((yyval).u.constant)= ZEND_ACC_STATIC;
grammar-line: 182
走了這個函數zend_do_verify_access_types
做了檢測,static不能用來限制abstract類的成員變量等
word: valname
grammar-line: 177
grammar-line: 169
word: test
grammar-line: 303
grammar-line: 309
grammar-line: 192
調用了zend_do_declare_property函數
通過CG(active_class_entry)檢測,接口不能添加成員變量
變量不能是abstact和final
檢查是否進行了重復定義
調用zend_declare_property_ex
通過access_type& ZEND_ACC_STATIC這個判斷出來是否為靜態變量
如果是靜態變量則target_symbol_table= &ce->default_static_members;
如果不是則target_symbol_table= &ce->default_properties;
最後zend_hash_update更新屬性字段
6 結論
類的普通變量和成員變量都存儲在類結構的屬性裡面,僅是存儲在的目標hash表不同
摘自 xiaoq3406的專欄