[問題]
儘管有程式設計經驗,但PHPPHP中的屬性預設錯誤令我困惑。代碼:
<code class="php">class Foo { public $path = array( realpath(".") ); }</code>
產生語法錯誤。但是,以下內容可以無縫運行:
<code class="php">$path = array( realpath(".") );</code>
問題出現了:為什麼不能在屬性預設值中呼叫函數?這是故意的還是實現中的缺陷?
[答案]
PHP 編譯器程式碼顯示此限制是故意的,儘管沒有官方的理由。可靠地實現此功能會帶來一定的挑戰,PHP 目前實現的限制就證明了這一點。
編譯器的語法將類別變數宣告定義為:
class_variable_declaration: //... | T_VARIABLE '=' static_scalar //... ;
因此,要指派像 $ 這樣的變數值路徑,預期值必須與靜態標量對齊。這包括其值也是靜態標量的陣列:
static_scalar: /* compile-time evaluated scalars */ //... | T_ARRAY '(' static_array_pair_list ')' // ... //... ;
如果語法允許使用以下與程式碼範例一致的語法,則腳本將遇到「無效的綁定類型」錯誤:
class_variable_declaration: //... | T_VARIABLE '=' T_ARRAY '(' array_pair_list ')' // ... ;
解析給定的程式碼範例顯示以下步驟:
zend_do_begin_class_declaration() // Adds an opcode array_init(), zend_do_add_static_array_element() // Do not create new opcodes, add array to class properties zend_do_declare_property() // Declares the property zend_do_early_binding() // Consumes the last opcode and evaluates it
如果操作碼不是預期的(例如,與函數或方法相關),則會引發錯誤。
允許非靜態陣列產生INIT_ARRAY 操作碼,這會破壞zend_do_early_binding():
DECLARE_CLASS 'Foo' SEND_VAL '.' DO_FCALL 'realpath' INIT_ARRAY
為了容納屬性預設值中的函數調用,需要一個作用域為類別變數聲明的新操作碼數組,類似到方法定義。然而,確定此類評估的時間表會帶來額外的挑戰。
其他動態語言已設法解決此問題,但 PHP 中仍然缺乏此功能,可能是由於其複雜性和感知的低優先級。
以上是為什麼 PHP 中的函數呼叫不能使用屬性預設值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!