<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                在面向對象語言中,都會內置一些語言內置提供的基本功能類,比如JavaScript中的Array,Number等類,PHP中也有很多這種類,比如Directory,stdClass,Exception等類,同時一些標準擴展比如PDO等擴展中也會定義一些類,PHP中類是不允許重復定義的,所以在編寫代碼時不允許定義已經存在的類。 同時PHP中有一些特殊的類:self,static和parent,相信讀者對這self和parent都比較熟悉了,而static特殊類是PHP5.3才引入的。 PHP中的static關鍵字非常多義: - 在函數體內的修飾變量的static關鍵字用于定義靜態局部變量。 - 用于修飾類成員函數和成員變量時用于聲明靜態成員。 - (PHP5.3)在作用域解析符(::)前又表示靜態延遲綁定的特殊類。 這個關鍵字修飾的意義都表示"靜態",在[PHP手冊中](http://cn.php.net/manual/en/language.oop5.paamayim-nekudotayim.php)提到self,parent和static這幾個關鍵字,但實際上除了static是關鍵字以外,其他兩個均不是關鍵字,在手冊的[關鍵字列表](http://cn.php.net/manual/en/reserved.keywords.php)中也沒有這兩個關鍵字,要驗證這一點很簡單: <?php var_dump(self); // -> string(4) "self" 上面的代碼并沒有報錯,如果你把error_reporting(E_ALL)打開,就能看到實際是什么情況了:運行這段代碼會出現“ Notice: Use of undefined constant self - assumed 'self'“,也就是說PHP把self當成一個普通常量了,嘗試未定義的常量會把產量本身當成一個字符串,例如上例的”self",不過同時會出一個NOTICE,這就是說self這個標示符并沒有什么特殊的。 <?php define('self',"stdClass"); echo self; // stdClass > 不同語言中的關鍵字的意義會有些區別,Wikipedia上的[解釋](http://en.wikipedia.org/wiki/Keyword_(computer_programming))是: 具有特殊含義的標示符或者單詞,從這個意義上說$this也算是一個關鍵字,但在PHP的關鍵字列表中并沒有。 PHP的關鍵字和C/C++一樣屬于保留字(關鍵字),關鍵字用于表示特定的語法形式,例如函數定義,流程控制等結構。 這些關鍵字有他們的特定的使用場景,而上面提到的self和parent并沒有這樣的限制。 ## self,parent,static類[]() 前面已經說過self的特殊性。self是一個特殊類,它指向當前類,但只有在類定義內部才有效,但也并不一定指向類本身這個特殊類,比如前面的代碼,如果放在類方法體內運行,echo self; 還是會輸出常量self的值,而不是當前類,它不止要求在類的定義內部,還要求在類的上下文環境,比如 new self()的時候,這時self就指向當前類,或者self::$static_varible,self::CONSTANT類似的作用域解析符號(::),這時的self才會作為指向本身的類而存在。 同理parent也和self類似。下面先看看在在類的環境下的編譯吧$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); } ; 在需要獲取類名時會執行zend_do_fetch_class()函數: 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; } // ... } 上面省略了一些無關的代碼,重點關注fetch_type變量。這是通過zend_get_class_fetch_type()函數獲取到的。 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引擎編譯類相關操作的代碼,下面就到執行階段了,self,parent等類的指向會在執行時進行獲取,找到執行opcode為ZEND_FETCH_CLASS的執行函數: 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; } 從這個函數就能看出端倪了,當需要獲取self類的時候,則將EG(scope)類返回,而EG(scope)指向的正是當前類。如果時parent類的話則從去EG(scope)->parent也就是當前類的父類,而static獲取的時EG(called_scope),分別說說EG宏的這幾個字段,前面已經介紹過EG宏,它可以展開為如下這個結構體: 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中類的內部結構表示,zend_class_entry有一個parent字段,也就是該類的父類。在EG結構體中的中called_scope會在執行過程中將當前執行的類賦值給called_scope,例如如下代碼: <?php class A { public static funcA() { static::funcB(); } } ? class B { public static funcB() { echo "B::funcB()"; } } ? B::funcA(); 代碼B::funcA()執行的時候,實際執行的是B的父類A中定義的funcA函數,A::funcA()執行時當前的類(scope)指向的是類A,而這個方法是從B類開始調用的,called_scope指向的是類B,static特殊類指向的正是called_scope,也就是當前類(觸發方法調用的類),這也是延遲綁定的原理。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看