摘要:靜態(tài)方法和屬性靜態(tài)方法是以類(lèi)作為作用域的函數(shù)。靜態(tài)方法不能訪(fǎng)問(wèn)這個(gè)類(lèi)中的普通屬性,因?yàn)槟切傩詫儆谝粋€(gè)對(duì)象,但可以訪(fǎng)問(wèn)靜態(tài)屬性。因此靜態(tài)方法和屬性又被稱(chēng)為類(lèi)變量和屬性,也就不能在靜態(tài)方法中使用偽變量。引入了延遲靜態(tài)綁定的概念。
靜態(tài)方法和屬性
靜態(tài)方法是以類(lèi)作為作用域的函數(shù)。靜態(tài)方法不能訪(fǎng)問(wèn)這個(gè)類(lèi)中的普通屬性,因?yàn)槟切傩?b>屬于一個(gè)對(duì)象,但可以訪(fǎng)問(wèn)靜態(tài)屬性。如果修改了一個(gè)靜態(tài)屬性,那么這個(gè)類(lèi)的所有實(shí)例都能訪(fǎng)問(wèn)到這個(gè)新值。
因?yàn)槭峭ㄟ^(guò)類(lèi)而不是實(shí)例來(lái)訪(fǎng)問(wèn)靜態(tài)元素,所以訪(fǎng)問(wèn)靜態(tài)元素時(shí)不再需要引用對(duì)象的變量,而是使用::來(lái)連接類(lèi)名和屬性或類(lèi)名和方法。
class StaicExample { static public $aNum = 0; static public function sayHello() { print "hello"; } } print StaicExample::$aNum; StaicExample::sayHello();
一個(gè)子類(lèi)可以使用parent關(guān)鍵字來(lái)訪(fǎng)問(wèn)父類(lèi),而不使用其類(lèi)名。要從當(dāng)前類(lèi)(不是子類(lèi))中訪(fǎng)問(wèn)靜態(tài)方法或?qū)傩?,可以使?b>self關(guān)鍵字。self指向當(dāng)前類(lèi),就像偽變量$this指向當(dāng)前對(duì)象一樣。因此,在StaticExample類(lèi)的外部可以使用其類(lèi)名訪(fǎng)問(wèn)屬性$aNum:
StaicExample::$aNum;
而在StaicExample類(lèi)內(nèi)部,可以使用self關(guān)鍵字:
class StaicExample { static public $aNum = 0; static public function sayHello() { self::$aNum++; print "hello (".self::$aNum.") "; } }
只有在使用parent關(guān)鍵字調(diào)用方法的時(shí)候,才能對(duì)一個(gè)非靜態(tài)方法進(jìn)行靜態(tài)形式的調(diào)用(使用::)。除非是訪(fǎng)問(wèn)一個(gè)被覆寫(xiě)的方法,否則永遠(yuǎn)只能使用::訪(fǎng)問(wèn)被明確聲明為static的方法或?qū)傩?。有時(shí)看到使用static語(yǔ)法來(lái)引用方法或?qū)傩?,可能并不意味著其中的方法或?qū)傩员仨毷庆o態(tài)的,只不過(guò)說(shuō)明它屬于特定的類(lèi)。
根據(jù)定義,不能在對(duì)象中調(diào)用靜態(tài)方法。因此靜態(tài)方法和屬性又被稱(chēng)為類(lèi)變量和屬性,也就不能在靜態(tài)方法中使用偽變量$this。
為什么要使用靜態(tài)方法或?qū)傩阅兀?/p>
在代碼中的任何地方都可用(假設(shè)你可以訪(fǎng)問(wèn)該類(lèi))。也就是說(shuō),你不需要在對(duì)象間傳遞類(lèi)的實(shí)例,也不需要將實(shí)例存放在全局變量中,就可以訪(fǎng)問(wèn)類(lèi)中方法。
類(lèi)的每個(gè)實(shí)例都可以訪(fǎng)問(wèn)類(lèi)中定義的靜態(tài)屬性,所以可以利用靜態(tài)屬性來(lái)設(shè)置值,該值可以被類(lèi)的所有對(duì)象使用。
不需要實(shí)例對(duì)象就能訪(fǎng)問(wèn)靜態(tài)屬性或方法,這樣就不用為了獲取一個(gè)簡(jiǎn)單的功能而實(shí)例化對(duì)象。
延遲靜態(tài)綁定:static關(guān)鍵字
靜態(tài)方法可以用作工廠(chǎng)方法,工廠(chǎng)方法是生成包含類(lèi)的實(shí)例的一種方法。
先看下面的重復(fù)代碼:
abstract class DomainObject { } class User extends DomainObject { public static function create() { return new User(); } } class Document extends DomainObject { public static function create() { return new Document(); } }
想必大家都不想為每個(gè)DomainObject子類(lèi)都創(chuàng)建與上面代碼類(lèi)似的標(biāo)準(zhǔn)代碼。如果把create()放在超類(lèi)呢?
abstract class DomainObject { public static function create() { return new self(); } } class User extends DomainObject { } class Document extends DomainObject { } Document::create();
這回看起來(lái)簡(jiǎn)潔多了。現(xiàn)在把常見(jiàn)的代碼放在一個(gè)位置,并使用self作為對(duì)該類(lèi)的引用。實(shí)際上,self對(duì)該類(lèi)所起的作用與$this對(duì)對(duì)象所起的作用并不完全相同。self指的不是調(diào)用上下文,而是解析上下文。因此,運(yùn)行剛才上面的代碼會(huì)得到:
PHP Fatal error: Cannot instantiate abstract class DomainObject in ...
因此,self被解析為定義create()的DomainObject,而不是解析為調(diào)用self的Document類(lèi)。PHP5.3之前,在這方面有嚴(yán)格的限制,產(chǎn)生很多笨拙的解決方案。PHP5.3引入了延遲靜態(tài)綁定的概念。該特性最明顯的標(biāo)志就是新關(guān)鍵字static。static類(lèi)似于self,但它指的是被調(diào)用的類(lèi)而不是包含類(lèi)。
在本例中,它的意思是調(diào)用Document::create()將生成一個(gè)新的Document對(duì)象,而不是試圖實(shí)例化一個(gè)DomainObject對(duì)象。
因此,現(xiàn)在在靜態(tài)上下文使用繼承關(guān)系。
abstract class DomainObject { public static function create() { return new static(); } } class User extends DomainObject { } class Document extends DomainObject { } print_r(Document::create());//Document Object {}
static關(guān)鍵字不僅僅可以用于實(shí)例化。和self和parent一樣,static還可以作為靜態(tài)方法調(diào)用的標(biāo)識(shí)符,甚至是從非靜態(tài)上下文中調(diào)用。
如果想為DomainObject引入組(group)的概念。默認(rèn)情況下,所有類(lèi)都屬于default類(lèi)別,但想可以為繼承層次結(jié)構(gòu)的某些分支重寫(xiě)類(lèi)別。
abstract class DomainObject { private $group; public function __construct() { $this->group = static::getGroup(); } public static function create() { return new static(); } static function getGroup() { return "default"; } } class User extends DomainObject { } class Document extends DomainObject { static function getGroup() { return "document"; } } class SpreadSheet extends Document { } print_r(User::create()); print_r(SpreadSheet::create());
在DomainObject類(lèi)中定義了構(gòu)造函數(shù)。該構(gòu)造函數(shù)使用static關(guān)鍵字調(diào)用靜態(tài)方法getGroup()。DomainObject提供了默認(rèn)實(shí)現(xiàn),但Document將其覆蓋了。創(chuàng)建的SpreadSheet新類(lèi)擴(kuò)展了Document類(lèi)。下面是打印結(jié)果:
User Object ( [group:DomainObject:private] => default ) SpreadSheet Object ( [group:DomainObject:private] => document )
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/28389.html
摘要:函數(shù)內(nèi)的變量靜態(tài)變量的理解靜態(tài)變量類(lèi)型說(shuō)明符是。靜態(tài)變量雖在程序的整個(gè)執(zhí)行過(guò)程中始終存在,但是在它作用域之外不能使用。靜態(tài)變量并不是說(shuō)其就不能改變值,不能改變值的量叫常量。 函數(shù)內(nèi)的static變量 static靜態(tài)變量的理解 靜態(tài)變量 類(lèi)型說(shuō)明符是static。靜態(tài)變量屬于靜態(tài)存儲(chǔ)方式,其存儲(chǔ)空間為內(nèi)存中的靜態(tài)數(shù)據(jù)區(qū)(在 靜態(tài)存儲(chǔ)區(qū)內(nèi)分配存儲(chǔ)單元),該區(qū)域中的數(shù)據(jù)在整個(gè)程序的運(yùn)行期間...
摘要:判斷是否存在構(gòu)造函數(shù),不存在直接實(shí)例化,存在則通過(guò)來(lái)獲取輸入函數(shù),并有相應(yīng)的方法解決依賴(lài)參數(shù)問(wèn)題,實(shí)現(xiàn)依賴(lài)注入。 Laravel 框架關(guān)鍵技術(shù)解析·讀書(shū)筆記(一) 第一章 入口文件 請(qǐng)求訪(fǎng)問(wèn)的入口文件,主要完成幾部分工作,分別是: 自動(dòng)加載函數(shù)的添加 服務(wù)器實(shí)例化與服務(wù)注冊(cè) 路由加載 請(qǐng)求實(shí)例化與路由分發(fā) 相應(yīng)生成與發(fā)送 其中,自動(dòng)加載函數(shù)用于包含引用文件,改文件是composer...
摘要:于是為了解決這個(gè)問(wèn)題,中引入了延遲靜態(tài)綁定這個(gè)概念。延遲靜態(tài)綁定這個(gè)代碼與之前的幾乎一致,不同點(diǎn)在于將換成了這個(gè)關(guān)鍵字,會(huì)解析為子類(lèi),而非父類(lèi),這樣就可以解決上面遇到的問(wèn)題,這就是的延遲靜態(tài)綁定。 使用場(chǎng)景 先來(lái)觀察以下代碼: abstract class base { //do sth } class aClass extends base{ public stat...
摘要:實(shí)驗(yàn)一個(gè)抽象類(lèi),有個(gè)方法,通過(guò)延遲靜態(tài)綁定實(shí)例化并返回。這里如果把注釋打開(kāi),打印的就是重寫(xiě)的值如果把抽象類(lèi)改成普通類(lèi),改成的方式實(shí)例化,結(jié)果就不同了,打印的屬性都是各自類(lèi)的屬性。 (原文地址,內(nèi)容以原文為準(zhǔn),可能修改或者補(bǔ)充:https://blog.tanteng.me/2017/...) 關(guān)于 PHP 的 new static 延遲靜態(tài)綁定,或者叫后期靜態(tài)綁定,在 Laravel...
摘要:有了的靜態(tài)延遲綁定功能,可以在運(yùn)行時(shí)動(dòng)態(tài)確定歸屬的類(lèi)。與是被討論最多,也是最容易引起誤用的組合。的用途看完與上述三個(gè)關(guān)鍵字的區(qū)別,的用途是不是呼之即出一句話(huà)總結(jié),那就是總是指向當(dāng)前類(lèi)及類(lèi)實(shí)例。 轉(zhuǎn)載請(qǐng)注明文章出處:https://tlanyan.me/self-in-php/ PHP群里有人詢(xún)問(wèn)self關(guān)鍵字的用法,答案是比較明顯的:靜態(tài)成員函數(shù)內(nèi)不能用this調(diào)用非成員函數(shù),但可以用...
閱讀 3951·2021-09-27 13:56
閱讀 950·2021-09-08 09:36
閱讀 895·2019-08-30 15:54
閱讀 679·2019-08-29 17:29
閱讀 997·2019-08-29 17:21
閱讀 1768·2019-08-29 16:59
閱讀 2850·2019-08-29 13:03
閱讀 3069·2019-08-29 12:47