亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

通過類名動(dòng)態(tài)生成對(duì)象

VEIGHTZ / 2787人閱讀

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

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

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

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

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

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

原理

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

從人的角度看,代碼意圖非常明顯:動(dòng)態(tài)生成類B的實(shí)例。但從執(zhí)行引擎的角度,完全是另外一回事。其實(shí)new $classname()背后的運(yùn)作行為類似于:

// 偽代碼
if (class_exists($str)) {
  $b = new $str();
  return $b;
}
throw ClassNotFoundException;

// 或者用反射
try {
  $reflectionClass = new ReflectionClass($str);
  $b = $reflectionClass.newInstance();
  return $b;
}
throw ClassNotFoundException;

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

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

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

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

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

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

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

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

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

總結(jié)

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

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

參考

PHP回顧之反射

PHP中的重載

Using namespaces: fallback to global function/constant

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/30910.html

相關(guān)文章

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

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

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

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

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

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

    weij 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<