摘要:保持目前的情況,除動態生成實例時需要完全限定類名,并無其他槽點。本文所討論的根據類名動態生成對象,就要無視當前所在或引入的名字空間,必須使用完全限定類名形式。作為對比,不能動態生成對象。
轉載請注明文章出處:https://tlanyan.me/dynamic-ne...問題
前幾天有人在PHP的QQ群里問生成對象的問題:
use AB; $b = new B(); // 正確 $str = "B"; $b = new $str(); // 錯誤,提示:類"B"未找到
類似問題五六年前碰到過,因此印象深刻。熱心提示要用 "完全限定類名" 形式,可惜連說兩遍,提問題的人都沒理解我說的(或者認為我的回復與其問題無關):
不得已下,寫下示范代碼并 @ 提問題的人,終于讓其明白:
原理問題解決了,背后的原理是什么?
從人的角度看,代碼意圖非常明顯:動態生成類B的實例。但從執行引擎的角度,完全是另外一回事。其實new $classname()背后的運作行為類似于:
// 偽代碼 if (class_exists($str)) { $b = new $str(); return $b; } throw ClassNotFoundException; // 或者用反射 try { $reflectionClass = new ReflectionClass($str); $b = $reflectionClass.newInstance(); return $b; } throw ClassNotFoundException;
要根據類名動態生成示例,首先要判斷類是否存在吧?PHP中與之相關的是class_exists函數和ReflectionClass類。在上面的例子中,只傳入字符串 "B",class_exists回返回true嗎?
答案是否定的。class_exists和ReflectionClass只會在全局類列表中根據名字查找,不會理會調用函數所在(或引入)的名字空間。同理,如果使用use引入類名并做別名(as),別名類在class_exists中也會返回false。
那么PHP能否改進一下class_exists和ReflectionClass的行為,讓其根據當前上下文判斷?
可以這么做,但是代價很大,原因包括:
class_exists和ReflectionClass都沒有指示程序上下文Context的參數;
PHP比較坑的一點:類名不會像函數、常量一樣往上逐級查找;
如果存在多個同名的類,加載哪個?如以下代碼所示:
不管采取哪種行為,都會招致吐槽。
保持目前的情況,除動態生成實例時需要完全限定類名,并無其他槽點。并且實現上簡單,行為明確且一致。
總結作為一門腳本語言,PHP非常的靈活,但也會帶來一些使用上的困惑。本文所討論的根據類名動態生成對象,就要無視當前所在或引入的名字空間,必須使用完全限定類名形式。
作為對比,C++不能動態生成對象。Java要用Class.forName的方式獲取class對象,然后再調用構造函數生成。Java不能直接new類名,避免了PHP中的坑,但Class.forName同樣需要完全限定類名,避免不明確行為。
參考PHP回顧之反射
PHP中的重載
Using namespaces: fallback to global function/constant
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30910.html
摘要:代理模式從類型上來說,可以分為靜態代理和動態代理兩種類型。然而今天的重點是我們都知道牛逼轟轟的的實現的一種方式是使用的動態代理另一種是,大部分人也會用的動態代理,不過沒有研究過的動態代理到底是怎么實現的。 動態代理 代理模式是設計模式中非常重要的一種類型,而設計模式又是編程中非常重要的知識點,特別是在業務系統的重構中,更是有舉足輕重的地位。代理模式從類型上來說,可以分為靜態代理和動態代...
摘要:動態代理深度解析引言說起動態代理,很多人可能都沒有直接去使用過。因為的動態代理只能代理接口,而不能代理原始的類。接下來是真正壓軸的環節,實現自己的動態代理類。 Java動態代理深度解析 引言 說起動態代理,很多人可能都沒有直接去使用過。但是只要用過Spring,那動態代理就是一個是個繞不過的坎,因為Spring的核心特性之一AOP就是基于動態代理來實現的,那么什么情況下需要用到動態代理...
摘要:如何修改代碼為了盡量減少程序員的工作,我們的代碼生成器在生成完后,還需要將方法的返回值自動修改成這個類。具體的實現到此為止,基本上代碼生成器的主要障礙都有了相應的處理辦法。 當前的狀況 一般做數據庫相關開發, 除非學習, 否則很少有人愿意直接使用JDBC。本來Java代碼就比較啰嗦了,而直接用JDBC寫代碼之啰嗦簡直有些令人發狂!所以在實際開發過程中,我們通常都會使用一些框架/庫來幫助...
閱讀 763·2019-08-29 12:49
閱讀 3550·2019-08-29 11:32
閱讀 3434·2019-08-26 10:43
閱讀 2402·2019-08-23 16:53
閱讀 2048·2019-08-23 15:56
閱讀 1695·2019-08-23 12:03
閱讀 2767·2019-08-23 11:25
閱讀 2084·2019-08-22 15:11