一文解決 PHP靜態(區域性/全域性)變數、auto(區域性/全域性)變數、類中static
阿新 • • 發佈:2018-11-03
一、靜態區域性變數、auto區域性變數、類中static
這是我的概念:
類屬性,類方法:是給類使用的,在類中使用 self::和 static:: 代表,供呼叫
例項屬性,例項方法:是給例項使用的,在類中使用 this-> 代表,供呼叫
<?php /** * User: X.W.X * Date: 2018-09-14 * Time: 13:57 * FileName: test.php * Introduce: */ // 當前 php7.0版本 好像還沒有 靜態函式,靜態類的概念,所以 不測試 // 以下是主要測試內容: // 測試 靜態區域性變數和auto區域性變數 的區別 // 測試 類中 靜態屬性和非靜態屬性 的區別 // 測試 類中 靜態方法和非靜態方法 的區別 class TestStatic{ // 類中有寫static的屬性和方法 ==> 類屬性和類方法 // 類中沒寫static的屬性和方法 ==> 例項屬性和例項方法 // 有static ==> 類屬性 // 可使用 self::或者static:: 呼叫 ==> 二者的區別: self:: 和 static:: 都代表者類,但self::始終代表當前類,而static:: 代表最後一次被重寫的類 public static $echo_static; // 無static ==> 例項屬性 // 可使用 $this-> 呼叫 public $echo_auto; protected $echo_protected; // 例項方法 ==> 測試(普通變數=auto變數) public function test_auto(){ // auto變數必須初始化 ==> 出函式之後,會被刪除回收 ==> 再次進入函式,繼續被初始化 $i = 0; $this->echo_auto = $this->echo_auto.strval($i).','; $i++; } // 靜態方法(類方法) ==> 測試(靜態變數=static變數) public static function test_static() { // 只初始化一次 ==> 出函式之後,會被記住不回收,但其作用範圍被侷限在函式內,因此跟全域性變數有所區別 // ==> 再次進入函式,不會被初始化,會從記住的值繼續開始 static $i; self::$echo_static = self::$echo_static.strval($i).','; $i++; } public function common() { foreach (range(0, 10) as $index) { // 展示 例項呼叫 $this->test_auto(); // 展示 靜態呼叫 static::test_static(); } } public function testInstanceInherit(){ // get_called_class() 獲得當前呼叫類名 $class = get_called_class(); echo '當前類名: '.$class." 測試 公開例項方法 重寫".PHP_EOL; } public static function testClassInherit(){ $class = get_called_class(); echo '當前類名: '.$class." 測試 公開類方法 重寫".PHP_EOL; } } // 生成例項 $test = new TestStatic(); // 測試 static變數和auto變數 $test->common(); // 測試 例項呼叫例項方法,注意:不使用$符號 echo $test->echo_auto.PHP_EOL; //echo $test->echo_static.PHP_EOL; // 例項呼叫類屬性 報錯,Accessing static property // 測試 類呼叫類方法,注意:使用$符號,為什麼呢?這是我的愚見:無例項化,那些類屬性沒被建立,因此使用$符號 echo TestStatic::$echo_static.PHP_EOL; //echo TestStatic::$echo_auto.PHP_EOL; // 類呼叫例項屬性 報錯,Access to undeclared static property /* result: 0,0,0,0,0,0,0,0,0,0,0, ,1,2,3,4,5,6,7,8,9,10, */ /** * 從以上結果可看出,php7.0版本 * auto變數必須初始化 ==> 出函式之後,會被刪除回收 ==> 再次進入函式,繼續被初始化 * static變數非必須初始化,預設初始化為null且只初始化一次 * ==> 出函式之後,會被記住不回收,但其作用範圍被侷限在函式內,因此跟全域性變數有所區別 * ==> 再次進入函式,不會被初始化,會從記住的值繼續開始 */ class TestStaticSub extends TestStatic { public function testInstanceInherit(){ $class = get_called_class(); echo '當前類名: '.$class." 測試 公開例項方法 重寫".PHP_EOL; echo '當前類名: '.$class." 這是 重寫內容".PHP_EOL; } public static function testClassInherit(){ $class = get_called_class(); echo '當前類名: '.$class." 測試 公開類方法 重寫".PHP_EOL; echo '當前類名: '.$class." 這是 重寫內容".PHP_EOL; } } // 父類TestStatic 例項 $test_static = new TestStatic(); // 子類TestStaticSub 例項 $test_static_sub = new TestStaticSub(); // 父類例項 呼叫父類例項方法 $test_static->testInstanceInherit(); // 父類例項 呼叫父類類方法 $test_static->testClassInherit(); // 子類例項 被重寫,呼叫子類例項方法,==> 被重寫規則:方法名和引數要都一樣才會被重寫 $test_static_sub->testInstanceInherit(); // 子類例項 被重寫,呼叫子類類方法 $test_static_sub->testClassInherit(); echo PHP_EOL; // 父類 呼叫 父類類方法 TestStatic::testClassInherit(); //TestStatic::testInstanceInherit(); // 父類 呼叫 父類例項方法 報錯,Non-static method // 子類 呼叫 子類方法 TestStaticSub::testClassInherit(); //TestStaticSub::testInstanceInherit(); // 子類 呼叫 子類例項方法 報錯,Non-static method // 從下面 結果 可看出 不管是類方法還是例項方法,只要方法名和引數相同,都會被重寫 形成類多型 // 那有 類多型 有沒有 例項多型呢? /* result: 當前類名: TestStatic 測試 公開例項方法 重寫 當前類名: TestStatic 測試 公開類方法 重寫 當前類名: TestStaticSub 測試 公開例項方法 重寫 當前類名: TestStaticSub 這是 重寫內容 當前類名: TestStaticSub 測試 公開類方法 重寫 當前類名: TestStaticSub 這是 重寫內容 當前類名: TestStatic 測試 公開類方法 重寫 當前類名: TestStaticSub 測試 公開類方法 重寫 當前類名: TestStaticSub 這是 重寫內容 */ /** * 從以上結果可看出,php7.0版本 * 1. 類方法會被例項所繼承,但類屬性暫時在當前版本是沒被例項所繼承,不像python3語言,例項預設繼承類中的類屬性和類方法 * 2. 也就是說,當前PHP版本中 ==> 例項是調用不了類屬性,但可呼叫類方法、例項屬性、例項方法 * 3. 若父類和子類中 名字和引數同時相同的,會被子類重寫,反而反之, */
結語:
類中static==>類屬性,供類使用
類中非static==>例項屬性,供例項使用
注意:例項中的屬性和方法 不會像Pyhon語言那樣 都預設把類中的屬性和方法 給繼承了,PHP7.0預設繼承只有方法,屬性要不要繼承自己開發
二、靜態全域性變數、auto全域性變數
// test1.php
const a = '常量被匯入';
$a = '普通全域性變數被匯入';
static $b = '靜態全域性變數被匯入';
global $c;
$c = 'global全域性變數被匯入';
// 此為 test.php檔案 // 測試 靜態全域性變數和auto全域性變數 include_once 'test1.php'; // 網上說:靜態全域性變數,被侷限於那個檔案內,但我不管咋測試都是被匯入 print_r(a.PHP_EOL); print_r($a.PHP_EOL); print_r($b.PHP_EOL); print_r($c); /* result: 常量被匯入 普通全域性變數被匯入 靜態全域性變數被匯入 global全域性變數被匯入 */
結語:
網上說的不一定是真的,需要自己驗證
三、static::、self::的區別
class A { public static function who() { echo __CLASS__; } public static function test() { self::who(); //AAA // static::who(); //ABB } } A::test(); class B extends A { public static function who() { echo __CLASS__; } } B::test(); class C extends B { } C::test(); /** * 若無重寫類屬性或類方法: * self和static的指向是一樣的 * 若有重寫: * self ==> 指向當前類,類似於直接使用類名 那為什麼不使用直接類名而使用self?圖省力 * static ==> 指向最後一次重寫的類,後期繫結 */