php后期静态绑定

在看Yii2代码的时候,有这么一段

1
2
3
4
5
6
7
8
9
10
11
if (isset(static::$classMap[$className])) {
$classFile = static::$classMap[$className];
if ($classFile[0] === '@') {
$classFile = static::getAlias($classFile);
}
} elseif (strpos($className, '\\') !== false) {
$classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php', false);
if ($classFile === false || !is_file($classFile)) {
return;
}
}

当时有点困惑,为啥用了个static::$classMap[$className],而不是self::$classMap[$className],细看了下self和static的区别
大体可以理解为static定义的function 如果子类又重新实现了的话,会用子类的结果(实际运行的时候的),而self永远是最开始定义的父类的结果

与self类似的还有 CLASS 和get_class() 只会是最开始定义的结果,不过注意get_class($this)会是实际运行时的类的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
class A {
static $staticString = "A static string";
public static function staticFunction() {
echo self::$staticString;
}
public static function foo() {
echo "Afoo:".__CLASS__."\n";
}
public static function selfFoo() {
echo "called class:".get_called_class()."\n";
echo "class:".get_class()."\n";
echo self::foo();
}
public static function staticFoo() {
echo "called class:".get_called_class()."\n";
echo "class:".get_class()."\n";
echo static::foo();
}
}
class B extends A {
static $staticString = "B static string";
public static function foo() {
echo "Bfoo:".__CLASS__."\n";
}
public static function parent() {
parent::selfFoo();
parent::staticFoo();
}
}
class C extends B {
public static function foo() {
echo __CLASS__;
}

}
B::selfFoo();
/*
输出结果
called class:B
class:A
Afoo:A
*/
B::staticFoo();
C::parent();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

<?php

class base_class
{
function say_a()
{
echo "'a' - said the " . __CLASS__ . "<br/>";
}

function say_b()
{
echo "'b' - said the " . get_class($this) . "<br/>";
}

}

class derived_class extends base_class
{
function say_a()
{
parent::say_a();
echo "'a' - said the " . __CLASS__ . "<br/>";
}

function say_b()
{
parent::say_b();
echo "'b' - said the " . get_class($this) . "<br/>";
}
}

$obj_b = new derived_class();

$obj_b->say_a();
echo "<br/>";
$obj_b->say_b();

?>

The output should look roughly like this:

‘a’ - said the base_class
‘a’ - said the derived_class

‘b’ - said the derived_class
‘b’ - said the derived_class