這篇文章主要介紹PHP保留類及特殊類是什么,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)是一家專業(yè)提供晉城企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站設(shè)計(jì)、做網(wǎng)站、成都h5網(wǎng)站建設(shè)、小程序制作等業(yè)務(wù)。10年已為晉城眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
在面向?qū)ο笳Z(yǔ)言中,都會(huì)內(nèi)置一些語(yǔ)言內(nèi)置提供的基本功能類,比如JavaScript中的Array,Number等類,PHP中也有很多這種類,比如Directory,stdClass,Exception等類,同時(shí)一些標(biāo)準(zhǔn)擴(kuò)展比如PDO等擴(kuò)展中也會(huì)定義一些類,PHP中類是不允許重復(fù)定義的,所以在編寫代碼時(shí)不允許定義已經(jīng)存在的類。
同時(shí)PHP中有一些特殊的類:self
,static
和parent
,相信讀者對(duì)這self和parent都比較熟悉了,而static特殊類是PHP5.3才引入的。
PHP中的static關(guān)鍵字非常多義:
● 在函數(shù)體內(nèi)的修飾變量的static關(guān)鍵字用于定義靜態(tài)局部變量。
● 用于修飾類成員函數(shù)和成員變量時(shí)用于聲明靜態(tài)成員。
● (PHP5.3)在作用域解析符(::)前又表示靜態(tài)延遲綁定的特殊類。
這個(gè)關(guān)鍵字修飾的意義都表示"靜態(tài)",在PHP手冊(cè)中提到self,parent和static這幾個(gè)關(guān)鍵字,但實(shí)際上除了static是關(guān)鍵字以外,其他兩個(gè)均不是關(guān)鍵字,在手冊(cè)的關(guān)鍵字列表中也沒(méi)有這兩個(gè)關(guān)鍵字,要驗(yàn)證這一點(diǎn)很簡(jiǎn)單:
<?php [var_dump](http://www.php.net/var_dump)(self); // -> string(4) "self"
上面的代碼并沒(méi)有報(bào)錯(cuò),如果你把error_reporting(E_ALL)打開(kāi),就能看到實(shí)際是什么情況了:運(yùn)行這段代碼會(huì)出現(xiàn)“ Notice: Use of undefined constant self - assumed 'self'“,也就是說(shuō)PHP把self當(dāng)成一個(gè)普通常量了,嘗試未定義的常量會(huì)把產(chǎn)量本身當(dāng)成一個(gè)字符串,例如上例的”self",不過(guò)同時(shí)會(huì)出一個(gè)NOTICE,這就是說(shuō)self這個(gè)標(biāo)示符并沒(méi)有什么特殊的。
<?php [define](http://www.php.net/define)('self',"stdClass"); [echo](http://www.php.net/echo) self; // stdClass
不同語(yǔ)言中的關(guān)鍵字的意義會(huì)有些區(qū)別,Wikipedia上的解釋是: 具有特殊含義的標(biāo)示符或者單詞,從這個(gè)意義上說(shuō)$this也算是一個(gè)關(guān)鍵字,但在PHP的關(guān)鍵字列表中并沒(méi)有。 PHP的關(guān)鍵字和C/C++一樣屬于保留字(關(guān)鍵字),關(guān)鍵字用于表示特定的語(yǔ)法形式,例如函數(shù)定義,流程控制等結(jié)構(gòu)。 這些關(guān)鍵字有他們的特定的使用場(chǎng)景,而上面提到的self和parent并沒(méi)有這樣的限制。
self,parent,static類
前面已經(jīng)說(shuō)過(guò)self的特殊性。self是一個(gè)特殊類,它指向當(dāng)前類,但只有在類定義內(nèi)部才有效,但也并不一定指向類本身這個(gè)特殊類,比如前面的代碼,如果放在類方法體內(nèi)運(yùn)行,echo self; 還是會(huì)輸出常量self的值,而不是當(dāng)前類,它不止要求在類的定義內(nèi)部,還要求在類的上下文環(huán)境,比如 new self()的時(shí)候,這時(shí)self就指向當(dāng)前類,或者self::$static_varible,self::CONSTANT類似的作用域解析符號(hào)(::),這時(shí)的self才會(huì)作為指向本身的類而存在。
同理parent也和self類似。下面先看看在在類的環(huán)境下的編譯吧$PHP_SRC/Zend/zend_language_parser.y:
class_name_reference: class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } | dynamic_class_name_reference { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } ;
在需要獲取類名時(shí)會(huì)執(zhí)行zend_do_fetch_class()函數(shù):
void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) { // ... opline->opcode = ZEND_FETCH_CLASS; if (class_name->op_type == IS_CONST) { int fetch_type; fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: case ZEND_FETCH_CLASS_PARENT: case ZEND_FETCH_CLASS_STATIC: SET_UNUSED(opline->op2); opline->extended_value = fetch_type; zval_dtor(&class_name->u.constant); break; default: zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC); opline->op2 = *class_name; break; } } else { opline->op2 = *class_name; } // ... }
上面省略了一些無(wú)關(guān)的代碼,重點(diǎn)關(guān)注fetch_type變量。這是通過(guò)zend_get_class_fetch_type()函數(shù)獲取到的。
int zend_get_class_fetch_type(const char *class_name, uint class_name_len) { if ((class_name_len == sizeof("self")-1) && !memcmp(class_name, "self", sizeof("self")-1)) { return ZEND_FETCH_CLASS_SELF; } else if ((class_name_len == sizeof("parent")-1) && !memcmp(class_name, "parent", sizeof("parent")-1)) { return ZEND_FETCH_CLASS_PARENT; } else if ((class_name_len == sizeof("static")-1) && !memcmp(class_name, "static", sizeof("static")-1)) { return ZEND_FETCH_CLASS_STATIC; } else { return ZEND_FETCH_CLASS_DEFAULT; } }
前面的代碼是Zend引擎編譯類相關(guān)操作的代碼,下面就到執(zhí)行階段了,self,parent等類的指向會(huì)在執(zhí)行時(shí)進(jìn)行獲取,找到執(zhí)行opcode為ZEND_FETCH_CLASS的執(zhí)行函數(shù):
zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) { zend_class_entry **pce; int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0; int silent = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0; fetch_type &= ZEND_FETCH_CLASS_MASK; check_fetch_type: switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: if (!EG(scope)) { zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); } return EG(scope); case ZEND_FETCH_CLASS_PARENT: if (!EG(scope)) { zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); } if (!EG(scope)->parent) { zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); } return EG(scope)->parent; case ZEND_FETCH_CLASS_STATIC: if (!EG(called_scope)) { zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); } return EG(called_scope); case ZEND_FETCH_CLASS_AUTO: { fetch_type = zend_get_class_fetch_type(class_name, class_name_len); if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { goto check_fetch_type; } } break; } if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) { if (use_autoload) { if (!silent && !EG(exception)) { if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { zend_error(E_ERROR, "Interface '%s' not found", class_name); } else { zend_error(E_ERROR, "Class '%s' not found", class_name); } } } } return NULL; } return *pce; }
從這個(gè)函數(shù)就能看出端倪了,當(dāng)需要獲取self類的時(shí)候,則將EG(scope)類返回,而EG(scope)指向的正是當(dāng)前類。如果時(shí)parent類的話則從去EG(scope)->parent也就是當(dāng)前類的父類,而static獲取的時(shí)EG(called_scope),分別說(shuō)說(shuō)EG宏的這幾個(gè)字段,前面已經(jīng)介紹過(guò)EG宏,它可以展開(kāi)為如下這個(gè)結(jié)構(gòu)體:
struct _zend_executor_globals { // ... zend_class_entry *scope; zend_class_entry *called_scope; /* Scope of the calling class */ // ... } struct _zend_class_entry { char type; char *name; zend_uint name_length; struct _zend_class_entry *parent; } #define struct _zend_class_entry zend_class_entry
其中的zend_class_entry就是PHP中類的內(nèi)部結(jié)構(gòu)表示,zend_class_entry有一個(gè)parent字段,也就是該類的父類。在EG結(jié)構(gòu)體中的中called_scope會(huì)在執(zhí)行過(guò)程中將當(dāng)前執(zhí)行的類賦值給called_scope,例如如下代碼:
<?php class A { public [static](http://www.php.net/static) funcA() { [static](http://www.php.net/static)::funcB(); } } class B { public [static](http://www.php.net/static) funcB() { [echo](http://www.php.net/echo) "B::funcB()"; } } B::funcA();
代碼B::funcA()執(zhí)行的時(shí)候,實(shí)際執(zhí)行的是B的父類A中定義的funcA函數(shù),A::funcA()執(zhí)行時(shí)當(dāng)前的類(scope)指向的是類A,而這個(gè)方法是從B類開(kāi)始調(diào)用的,called_scope指向的是類B,static特殊類指向的正是called_scope,也就是當(dāng)前類(觸發(fā)方法調(diào)用的類),這也是延遲綁定的原理。
以上是PHP保留類及特殊類是什么的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
網(wǎng)站標(biāo)題:PHP保留類及特殊類是什么
網(wǎng)站網(wǎng)址:http://www.rwnh.cn/article20/ihjgjo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站設(shè)計(jì)公司、、網(wǎng)站維護(hù)、定制開(kāi)發(fā)、用戶體驗(yàn)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)