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

PHP 靜態綁定 vs 動態綁定:self 與 static 關鍵字的核心區別與實戰應用

     編輯:PHP 相關知識

繼承體系中靜態方法調用的「編譯期」與「運行期」差異

PHP 5.3 引入靜態延遲綁定,static:: 關鍵字徹底改變了繼承中靜態成員的調用語義。本文通過最小化代碼演示核心差異,並給出選型原則。

核心差異一覽

關鍵字綁定時機解析目標典型場景
self::編譯期 (早期綁定)當前定義類 (寫代碼時所在類)內部實現細節、不希望被子類覆寫
static::運行期 (延遲綁定)實際調用類 (誰調用就解析誰)可擴展的工廠方法、ActiveRecord 查詢、模板方法模式

演示代碼:self 綁定父類

<?php
class Car {
    public static function model() {
        self::getModel(); // 編譯期鎖定 Car::getModel
    }
    protected static function getModel() {
        echo "This is a Car model\n";
    }
}

class Taxi extends Car {
    protected static function getModel() {
        echo "This is a Taxi model\n";
    }
}

Car::model();  // This is a Car model
Taxi::model(); // This is a Car model  ← 子類調用父類方法,self 仍指向父類

演示代碼:static 動態綁定子類

<?php
class Car {
    public static function model() {
        static::getModel(); // 運行期解析:誰調用 model() 就用誰的 getModel
    }
    protected static function getModel() {
        echo "This is a Car model\n";
    }
}

class Taxi extends Car {
    protected static function getModel() {
        echo "This is a Taxi model\n";
    }
}

Car::model();  // This is a Car model
Taxi::model(); // This is a Taxi model  ← 動態綁定生效

實戰場景:ActiveRecord 基類

abstract class Model {
    protected static string $table = '';

    // 靜態工廠:動態綁定獲取子類表名
    public static function find(int $id): ?static {
        $table = static::$table; // 關鍵:static:: 獲取子類靜態屬性
        $sql = "SELECT * FROM {$table} WHERE id = ?";
        // ... 執行查詢並返回 static 實例
    }

    // 內部輔助:不希望被覆寫,用 self
    private static function escape(string $val): string {
        return addslashes($val);
    }
    public static function query(string $sql) {
        self::escape($sql); // 內部實現細節,鎖定父類
    }
}

class User extends Model {
    protected static string $table = 'users';
}
class Order extends Model {
    protected static string $table = 'orders';
}

$user = User::find(1);   // 查 users 表
$order = Order::find(1); // 查 orders 表

進階:forward_static_call / get_called_class

class A {
    public static function who() {
        echo get_called_class() . "\n"; // 等同於 static::class
    }
}
class B extends A {}
B::who(); // B

// 手動觸發延遲綁定
forward_static_call(['B', 'who']); // B

選型決策樹

  1. 方法是否需要被子類覆寫/擴展? → 是 → static:: / 否 → self::
  2. 是否在構建可複用的基類/框架代碼? → 大量使用 static:: 實現多態。
  3. 內部私有輔助方法、不希望外部干預? → self:: (或 private static)。

常見誤區

  • ❌ self:: 能訪問子類屬性 —— 不能,編譯期已鎖定。
  • ❌ static:: 有性能損耗 —— 微乎其微,PHP 7+ 高度優化。
  • ✅ static:: 可用於屬性、方法、常量、new static() 實例化。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved