在laravel中,self關鍵字用于替代類名,可以引用當前類的靜態成員變量和靜態函數,也用于抑制多態行為,可以引用當前類的函數而非子類中覆蓋的實現,self總是指向當前類以及類實例。
本文操作環境:Windows10系統、Laravel6版、Dell G3電腦。
laravel中self的用法是什么
靜態成員函數內不能用?this?調用非成員函數,但可以用?self?調用靜態成員函數/變量/常量;其他成員函數可以用?self?調用靜態成員函數以及非靜態成員函數。隨著討論的深入,發現?self?并沒有那么簡單。鑒于此,本文先對幾個關鍵字做對比和區分,再總結?self?的用法。
與?parent?、?Static?以及?this?的區別
要想將徹底搞懂?self?,要與?parent?、?static?以及?this?區分開。以下分別做對比。
parent
self?與?parent?的區分比較容易:?parent?引用父類/基類被隱蓋的方法(或變量),?self則引用自身方法(或變量)。例如構造函數中調用父類構造函數:
class?Base?{ ????public?function?__construct()?{ ????????echo?"Base?contructor!",?php_EOL; ????} } class?Child?{ ????public?function?__construct()?{ ????????parent::__construct(); ????????echo?"Child?contructor!",?PHP_EOL; ????} } new?Child; //?輸出: //?Base?contructor! //?Child?contructor!
static
static?常規用途是修飾函數或變量使其成為類函數和類變量,也可以修飾函數內變量延長其生命周期至整個應用程序的生命周期。但是其與?self?關聯上是PHP 5.3以來引入的新用途:靜態延遲綁定。
有了?static?的靜態延遲綁定功能,可以在運行時動態確定歸屬的類。例如:
class?Base?{ ????public?function?__construct()?{ ????????echo?"Base?constructor!",?PHP_EOL; ????} ????public?static?function?getSelf()?{ ????????return?new?self(); ????} ????public?static?function?getInstance()?{ ????????return?new?static(); ????} ????public?function?selfFoo()?{ ????????return?self::foo(); ????} ????public?function?staticFoo()?{ ????????return?static::foo(); ????} ????public?function?thisFoo()?{ ????????return?$this->foo(); ????} ????public?function?foo()?{ ????????echo??"Base?Foo!",?PHP_EOL; ????} } class?Child?extends?Base?{ ????public?function?__construct()?{ ????????echo?"Child?constructor!",?PHP_EOL; ????} ????public?function?foo()?{ ????????echo?"Child?Foo!",?PHP_EOL; ????} } $base?=?Child::getSelf(); $child?=?Child::getInstance(); $child->selfFoo(); $child->staticFoo(); $child->thisFoo();
程序輸出結果如下:
Base?constructor! Child?constructor! Base?Foo! Child?Foo! Child?Foo!
在函數引用上,?self?與?static?的區別是:對于靜態成員函數,?self?指向代碼當前類,?static?指向調用類;對于非靜態成員函數,?self?抑制多態,指向當前類的成員函數,?static?等同于?this?,動態指向調用類的函數。
parent?、?self?、?static?三個關鍵字聯合在一起看挺有意思,分別指向父類、當前類、子類,有點“過去、現在、未來”的味道。
this
self?與?this?是被討論最多,也是最容易引起誤用的組合。兩者的主要區別如下:
- this?不能用在靜態成員函數中,?self?可以;
- 對靜態成員函數/變量的訪問, 建議 用?self?,不要用?$this::?或?$this->?的形式;
- 對非靜態成員變量的訪問,不能用?self?,只能用?this?;
- this?要在對象已經實例化的情況下使用,?self?沒有此限制;
- 在非靜態成員函數內使用,?self?抑制多態行為,引用當前類的函數;而?this?引用調用類的重寫(override)函數(如果有的話)。
self?的用途
看完與上述三個關鍵字的區別,?self?的用途是不是呼之即出?一句話總結,那就是:?self總是指向“當前類(及類實例)”。詳細說則是:
- 替代類名,引用當前類的靜態成員變量和靜態函數;
- 抑制多態行為,引用當前類的函數而非子類中覆蓋的實現;
槽點
- 這幾個關鍵字中,只有?this?要加?$?符號且必須加,強迫癥表示很難受;
- 靜態成員函數中不能通過?$this->?調用非靜態成員函數,但是可以通過?self::?調用,且在調用函數中未使用?$this->?的情況下還能順暢運行。此行為貌似在不同PHP版本中表現不同,在當前的7.3中ok;
- 在靜態函數和非靜態函數中輸出?self?,猜猜結果是什么?都是?String(4) “self”?,迷之輸出;
- return $this instanceof static::class;?會有語法錯誤,但是以下兩種寫法就正常:
$class = static::class;
return $this instanceof $class;
// 或者這樣:
return $this instanceof static;
【相關推薦:laravel視頻教程】