本文來自pilishen.com----原文連接; 歡迎來和pilishen一塊兒學習php&Laravel;學習羣:109256050php
該篇屬於《Laravel底層核心技術實戰揭祕》這一課程《laravel底層核心概念解析》這一章的擴展閱讀。因爲要真正學好laravel底層,有些PHP相關的知識必須得了解,考慮到學員們的基礎差別,爲了不視頻當中過於詳細而連篇累牘,故將一些laravel底層實現相關的PHP知識點以文章形式呈現,供你們預習和隨時查閱。laravel
以前咱們講過靜態調用綁定(late static binding),nice,如今來考考你唄~ :smirk:bash
<?php
class Foo {
protected static $instance;
public static function setInstance($ins)
{
static::$instance = $ins;
}
public static function getInstance()
{
return static::$instance;
}
}
class Bar extends Foo {
}
Bar::setInstance('pilishen.com');
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
?>
複製代碼
你說兩個輸出結果分別是啥呢?app
echo Bar::getInstance() .'<br>';
輸出的確定是pilishen.com
,問題是echo Foo::getInstance() .'<br>';
.post
咱們知道static::
指向的是實際調用它的class,因此Bar::setInstance('pilishen.com');
執行的時候,在setInstance()
方法裏至關因而Bar::$instance = 'pilishen.com'
,也便是class Bar
的靜態屬性$instance
設置成了pilishen.com
,而父類class Foo
的靜態屬性$instance
沒動着它,因此應該仍是空的,對吧?學習
現實是殘酷的: :open_mouth:測試
pilishen.com
pilishen.com
複製代碼
好吧,現實是須要接受的,繼續做! :smiling_imp:ui
...
class Baz extends Foo {
}
Bar::setInstance('pilishen.com');
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
echo '<hr>';
Baz::setInstance('laravel');
echo Baz::getInstance() .'<br>';
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
?>
複製代碼
咱們又搞了一個class Baz
,也是擴展了class Foo
,而後Baz::setInstance('laravel');
,這個時候很顯然Baz
的$instance
是laravel
了,問題是Bar
和Foo
的呢?咱們知道它兩個以前都是pilishen.com
,再來接受下現實? :scream:this
pilishen.com
pilishen.com
laravel
laravel
laravel
複製代碼
好吧,牽一髮動全身!子類能改變父類?!子類能改變子類?!厲害了哦~ :thumbsup:spa
爲了測試這只是靜態屬性的問題,也即證實一下咱們傳統的關於屬性繼承的思路沒錯,咱們改一下:
<?php
class Foo {
protected $instance='Null';
public function setInstance($ins)
{
$this->instance = $ins;
}
public function getInstance()
{
return $this->instance;
}
}
class Bar extends Foo {
}
class Baz extends Foo {
}
$bar = new Bar;
$bar->setInstance('pilishen.com');
echo $bar->getInstance() .'<br>';
echo (new Foo)->getInstance() .'<br>';
echo '<hr>';
$baz = new Baz;
$baz->setInstance('laravel');
echo $baz->getInstance() .'<br>';
echo $bar->getInstance() .'<br>';
echo (new Foo)->getInstance() .'<br>';
?>
複製代碼
如今的現實就是能夠接受的了:
pilishen.com
Null
laravel
pilishen.com
Null
複製代碼
因此,靜態屬性的繼承跟咱們默認想象的不同哦: :sunglasses:
儘管咱們在子類裏能夠獲取它,能夠修改它,可是這個它,指向的都是父類裏的那個靜態屬性,確實是子類能改變父類,子類能改變子類。也或者說,全部的父類和子類,都是共享這一個靜態屬性。
固然,上面的狀況僅發生在你的子類裏,沒有額外定義一個同名靜態屬性的狀況下,若是這樣:
<?php
class Foo {
protected static $instance='null';
public static function setInstance($ins)
{
static::$instance = $ins;
}
public static function getInstance()
{
return static::$instance;
}
}
class Bar extends Foo {
protected static $instance;
}
class Baz extends Foo {
protected static $instance;
}
Bar::setInstance('pilishen.com');
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
echo '<hr>';
Baz::setInstance('laravel');
echo Baz::getInstance() .'<br>';
echo Bar::getInstance() .'<br>';
echo Foo::getInstance() .'<br>';
?>
複製代碼
這裏咱們在子類裏面都額外定義了一個同名的$instance
,這個時候就是各自的是各自的了,就不是共享了:
pilishen.com
null
laravel
pilishen.com
null
複製代碼
好了,知道這些個有什麼用呢?
laravel裏大量使用了靜態屬性,固然也包括靜態調用綁定,那麼你在查看源碼的時候就要注意這一點嘍~父類和子類是共享的一個靜態屬性嗎?仍是子類裏面有從新定義呢?子類更改靜態屬性,會影響父類嗎? :sleeping:
最簡單的,laravel如何保證整個程序,那麼多個類,他們在運行的時候都是用的同一個laravel實例自己呢?都是同一個$app
呢?如今明白了吧~ :unamused:
不明白也沒關係,回頭咱們在《Laravel底層核心技術實戰揭祕》中一一詳解,記得有這麼回事就好~ :muscle: