首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP static 關鍵字深度解析:靜態屬性、靜態方法、靜態變量與繼承行為

     編輯:PHP 相關知識

static 是 PHP 面向對象編程中極具特色的關鍵字,它改變了成員屬於「實例」還是「類」的歸屬關係,也賦予了函數內變量「跨調用保持狀態」的能力。本文從語法、記憶體模型、繼承規則、常見誤區四個維度徹底講透。

一、靜態屬性:屬於類,不屬於實例

<?php
class Person {
    public static $country = "中國";  // 靜態屬性
    public $name = "張三";            // 實例屬性
}

echo Person::$country;  // 輸出:中國(無需實例化)
$p1 = new Person();
// echo $p1->country;  // 錯誤:靜態屬性不能通過對象訪問
$p1->name = "李四";     // 正常:實例屬性屬於對象

記憶體模型:靜態屬性在類加載時分配一次內存,所有實例共享同一塊地址;實例屬性隨 new 分配,各自獨立。

二、靜態方法:無 $this,可直接類名調用

class Person {
    public static $country = "中國";
    public static function myCountry() {
        echo "我是 " . self::$country . " 人<br>"; // 內部用 self::
    }
    public function sayHello() {
        echo "Hello, I'm " . $this->name . "<br>"; // 非靜態可用 $this
    }
}

Person::myCountry();      // 類名調用
$p = new Person();
$p->myCountry();          // 對象調用靜態方法:合法但不推薦(易誤導)
// $p->sayHello();       // 需實例化

核心限制:靜態方法內 不可使用 $this,不可訪問非靜態屬性/方法。但可訪問靜態屬性/方法(用 self:: 或 static::)。

三、靜態變量:函數內的「持久化局部變量」

function counter() {
    static $count = 0;  // 僅初始化一次
    $count++;
    echo $count . "<br>";
}
counter(); // 1
counter(); // 2
counter(); // 3
  • 僅在首次調用時初始化,之後保持值不銷毀。
  • 只能初始化為字面量或常量表達式,不能用函數返回值(如 static $x = strlen("abc"); ❌)。
  • 遞歸場景極其實用:遞歸深度計數、緩存中間結果。

遞歸計數範例

function recurse($n) {
    static $depth = 0;
    $depth++;
    echo "Depth: $depth<br>";
    if ($depth < $n) recurse($n);
    $depth--; // 回溯恢復
}
recurse(3);

四、繼承中的靜態行為:self:: vs static:: vs parent::

class ParentClass {
    public static $who = "Parent";
    public static function test() {
        echo "self::\$who = " . self::$who . "<br>";      // 編譯期綁定 → Parent
        echo "static::\$who = " . static::$who . "<br>";  // 運行期綁定 → 實際調用類
    }
}
class ChildClass extends ParentClass {
    public static $who = "Child";
}
ChildClass::test();

輸出:

self::$who = Parent
static::$who = Child
關鍵字綁定時機訪問靜態屬性訪問靜態方法
self::編譯期(定義所在類)✅✅
static::運行期(實際調用類,晚期靜態綁定 LSB)✅✅
parent::編譯期(父類)✅✅
類名::編譯期(指定類)✅✅
$obj->運行期(對象實例)❌ 靜態屬性✅ 僅靜態方法

五、常見誤區與最佳實踐

  1. 誤區:$obj->staticProp 可讀寫靜態屬性。
    事實:PHP 允許但會觸發 E_DEPRECATED(8.1+),語義混淆。統一用 Class::$prop。
  2. 誤區:靜態方法可隨意改為非靜態。
    事實:若方法內用 self:: 調用其他靜態方法,改為非靜態後 self:: 仍指向原類,導致 LSB 失效。重構時需同步改為 static::。
  3. 最佳實踐:
    • 工具類、單例、配置管理、緩存容器 → 靜態屬性/方法。
    • 狀態隨實例變化 → 非靜態。
    • 函數內需記憶上次結果 → static $var。
    • 繼承體系中需多態行為 → static::(LSB)。

六、單例模式標準實現(靜態綜合應用)

class Singleton {
    private static $instance = null;
    private function __construct() {}
    private function __clone() {}
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    public function doSomething() { echo "Working...<br>"; }
}
Singleton::getInstance()->doSomething();

總結

static 三大用法——靜態屬性/方法(類級共享)、靜態變量(函數級持久)、晚期靜態綁定 static::(繼承多態)——各有其記憶體語義與適用場景。搞清 self::(編譯期)與 static::(運行期)的區別,是進階 PHP OOP 的分水嶺。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved