self::指向定义时的类,static::指向运行时调用类。例如Base类中test()方法用self::who()始终调用Base的who(),而static::who()在Child类调用时会调用Child的who(),实现静态多态性。

self::
static::
self::
static::
要理解
self::
static::
self::
self::
而
static::
static::
static::
static::
我们来看一个经典的例子,这能最直观地展现它们的行为差异:
立即学习“PHP免费学习笔记(深入)”;
class Base {
public static function who() {
echo __CLASS__; // __CLASS__ 总是返回当前代码所在的类名
}
public static function test() {
echo "self::who() output: ";
self::who(); // 总是调用 Base::who()
echo "\n";
echo "static::who() output: ";
static::who(); // 调用运行时实际发起调用的类的 who() 方法
echo "\n";
}
}
class Child extends Base {
public static function who() {
echo __CLASS__; // 覆盖了父类的 who() 方法
}
}
echo "--- Calling from BaseClass ---\n";
Base::test();
// 预期输出:
// self::who() output: Base
// static::who() output: Base
echo "\n--- Calling from ChildClass ---\n";
Child::test();
// 预期输出:
// self::who() output: Base
// static::who() output: Child从上面的输出你可以清楚地看到:
Base::test()
self::who()
static::who()
Base
Base
self::
test
Base
Child::test()
self::who()
Base
test
Base
self::
static::who()
Child
Child
Child
who()
在 PHP 5.3 之前,我们只有
self::
A
B
self::B()
B
A
B
self::B()
B
举个例子,假设我们有一个基类
Logger
log()
self::getPrefix()
class OldLogger {
protected static function getPrefix() {
return "LOG: ";
}
public static function log($message) {
echo self::getPrefix() . $message . "\n";
}
}
class ErrorLogger extends OldLogger {
protected static function getPrefix() {
return "ERROR: "; // 期望这个前缀被使用
}
}
echo "OldLogger::log('Message');\n";
OldLogger::log('Message'); // 输出: LOG: Message
echo "ErrorLogger::log('Error Message');\n";
ErrorLogger::log('Error Message'); // 输出: LOG: Error Message (问题所在!)你看,
ErrorLogger::log()
self::
getPrefix()
OldLogger
为了解决这个问题,PHP 5.3 引入了后期静态绑定,并提供了
static::
static::
log
class NewLogger {
protected static function getPrefix() {
return "LOG: ";
}
public static function log($message) {
echo static::getPrefix() . $message . "\n"; // 使用 static::
}
}
class NewErrorLogger extends NewLogger {
protected static function getPrefix() {
return "ERROR: ";
}
}
echo "NewLogger::log('Message');\n";
NewLogger::log('Message'); // 输出: LOG: Message
echo "NewErrorLogger::log('Error Message');\n";
NewErrorLogger::log('Error Message'); // 输出: ERROR: Error Message (这正是我们想要的!)通过
static::
log()
NewErrorLogger
NewErrorLogger
getPrefix()
self::
static::
在日常开发中,选择
self::
static::
优先使用 self::
self::
self::CONSTANT_NAME
static::CONSTANT_NAME
self::
parent::method()
self::
优先使用 static::
实现静态多态性: 这是
static::
static::
工厂方法(Factory Methods):
return new static();
class Car {
public static function create() {
return new static(); // 返回 Car 或其子类的实例
}
}
class Sedan extends Car {}
class SUV extends Car {}
$sedan = Sedan::create(); // $sedan 是 Sedan 的实例
$suv = SUV::create(); // $suv 是 SUV 的实例动态配置或状态管理: 当你希望静态属性(例如配置项、状态标志)能够在继承链中被子类“覆盖”时,使用
static::$property
class Settings {
protected static $theme = 'default';
public static function getTheme() {
return static::$theme; // 允许子类覆盖
}
}
class AdminSettings extends Settings {
protected static $theme = 'admin';
}
echo Settings::getTheme() . "\n"; // default以上就是php static:: 和 self:: 有什么区别 php静态绑定中static与self的差异的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号