PHP靜態屬性(static variable)的繼承(inheritance),尤爲是在靜態調用綁定(late static binding)中

本文來自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$instancelaravel了,問題是BarFoo的呢?咱們知道它兩個以前都是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:

相關文章
相關標籤/搜索