成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

通過類名動態(tài)生成對象

VEIGHTZ / 2695人閱讀

摘要:保持目前的情況,除動態(tài)生成實例時需要完全限定類名,并無其他槽點。本文所討論的根據(jù)類名動態(tài)生成對象,就要無視當(dāng)前所在或引入的名字空間,必須使用完全限定類名形式。作為對比,不能動態(tài)生成對象。

轉(zhuǎn)載請注明文章出處:https://tlanyan.me/dynamic-ne...
問題

前幾天有人在PHP的QQ群里問生成對象的問題:

use AB;
$b = new B();  // 正確
$str = "B";
$b = new $str(); // 錯誤,提示:類"B"未找到

類似問題五六年前碰到過,因此印象深刻。熱心提示要用 "完全限定類名" 形式,可惜連說兩遍,提問題的人都沒理解我說的(或者認為我的回復(fù)與其問題無關(guān)):

不得已下,寫下示范代碼并 @ 提問題的人,終于讓其明白:

原理

問題解決了,背后的原理是什么?

從人的角度看,代碼意圖非常明顯:動態(tài)生成類B的實例。但從執(zhí)行引擎的角度,完全是另外一回事。其實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;

要根據(jù)類名動態(tài)生成示例,首先要判斷類是否存在吧?PHP中與之相關(guān)的是class_exists函數(shù)和ReflectionClass類。在上面的例子中,只傳入字符串 "B",class_exists回返回true嗎?

答案是否定的。class_existsReflectionClass只會在全局類列表中根據(jù)名字查找,不會理會調(diào)用函數(shù)所在(或引入)的名字空間。同理,如果使用use引入類名并做別名(as),別名類在class_exists中也會返回false。

那么PHP能否改進一下class_existsReflectionClass的行為,讓其根據(jù)當(dāng)前上下文判斷?

可以這么做,但是代價很大,原因包括:

class_existsReflectionClass都沒有指示程序上下文Context的參數(shù);

PHP比較坑的一點:類名不會像函數(shù)、常量一樣往上逐級查找;

如果存在多個同名的類,加載哪個?如以下代碼所示:

不管采取哪種行為,都會招致吐槽。

保持目前的情況,除動態(tài)生成實例時需要完全限定類名,并無其他槽點。并且實現(xiàn)上簡單,行為明確且一致。

總結(jié)

作為一門腳本語言,PHP非常的靈活,但也會帶來一些使用上的困惑。本文所討論的根據(jù)類名動態(tài)生成對象,就要無視當(dāng)前所在或引入的名字空間,必須使用完全限定類名形式。

作為對比,C++不能動態(tài)生成對象。Java要用Class.forName的方式獲取class對象,然后再調(diào)用構(gòu)造函數(shù)生成。Java不能直接new類名,避免了PHP中的坑,但Class.forName同樣需要完全限定類名,避免不明確行為。

參考

PHP回顧之反射

PHP中的重載

Using namespaces: fallback to global function/constant

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/30910.html

相關(guān)文章

  • 【干貨】JDK動態(tài)代理的實現(xiàn)原理以及如何手寫一個JDK動態(tài)代理

    摘要:代理模式從類型上來說,可以分為靜態(tài)代理和動態(tài)代理兩種類型。然而今天的重點是我們都知道牛逼轟轟的的實現(xiàn)的一種方式是使用的動態(tài)代理另一種是,大部分人也會用的動態(tài)代理,不過沒有研究過的動態(tài)代理到底是怎么實現(xiàn)的。 動態(tài)代理 代理模式是設(shè)計模式中非常重要的一種類型,而設(shè)計模式又是編程中非常重要的知識點,特別是在業(yè)務(wù)系統(tǒng)的重構(gòu)中,更是有舉足輕重的地位。代理模式從類型上來說,可以分為靜態(tài)代理和動態(tài)代...

    forsigner 評論0 收藏0
  • Java動態(tài)代理深度解析

    摘要:動態(tài)代理深度解析引言說起動態(tài)代理,很多人可能都沒有直接去使用過。因為的動態(tài)代理只能代理接口,而不能代理原始的類。接下來是真正壓軸的環(huán)節(jié),實現(xiàn)自己的動態(tài)代理類。 Java動態(tài)代理深度解析 引言 說起動態(tài)代理,很多人可能都沒有直接去使用過。但是只要用過Spring,那動態(tài)代理就是一個是個繞不過的坎,因為Spring的核心特性之一AOP就是基于動態(tài)代理來實現(xiàn)的,那么什么情況下需要用到動態(tài)代理...

    whinc 評論0 收藏0
  • 如何根據(jù)動態(tài)SQL代碼自動生成DTO

    摘要:如何修改代碼為了盡量減少程序員的工作,我們的代碼生成器在生成完后,還需要將方法的返回值自動修改成這個類。具體的實現(xiàn)到此為止,基本上代碼生成器的主要障礙都有了相應(yīng)的處理辦法。 當(dāng)前的狀況 一般做數(shù)據(jù)庫相關(guān)開發(fā), 除非學(xué)習(xí), 否則很少有人愿意直接使用JDBC。本來Java代碼就比較啰嗦了,而直接用JDBC寫代碼之啰嗦簡直有些令人發(fā)狂!所以在實際開發(fā)過程中,我們通常都會使用一些框架/庫來幫助...

    weij 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<