之前有人詢問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;
很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那里入手去提升,對此我整理了一些資料,包括但不限于:分布式架構、高可擴展、高性能、高并發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階干貨需要的可以免費分享給大家,需要的加群(點擊→)677079770
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/105966.html
標籤:PHP
