思考并回答以下问题:
从这个名字的定义提取出两个关键点,第一点静态,也就是说这个功能只适用于静态属性或静态方法。
第二点延迟绑定,这个根据下面代码就可以很好的理解。
看一下这个例子: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
31class A
{
static $name = "Tom";
public function printName()
{
echo self::$name."\n";
self::fun();
}
static function fun()
{
echo "A Class\n";
}
}
class B extends A
{
static $name = "Jon";
static function fun()
{
echo "B Class\n";
}
}
$obj = new B();
$obj->printName();
// 输出结果
// Tom
// A Class
我在printName函数里面使用了self关键字,self是指向当前类的”指针”,所以很多人会理想的认为输出结果会是这样:1
2// Join
// B Class
是这样的,在定义A类的时候,在函数printName里面使用self关键字调用了静态方法或属性,但是这个函数一旦定义好,A类的静态方法和属性就被绑定到函数了,不要去追究为什么,php就是这么实现的,但是我们现在要实现这样的效果,就是函数定义好后里面使用到的静态方法和属性不要立即绑定死,而是根据最终继承的类来确定绑定。
所以php在5.5以后使用了static关键字来解决这个问题,解决后的代码例子如下: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
31class A
{
static $name = "Tom";
public function printName()
{
echo static::$name."\n";
static::fun();
}
static function fun()
{
echo "A Class\n";
}
}
class B extends A
{
static $name = "Jon";
static function fun()
{
echo "B Class\n";
}
}
$obj = new B();
$obj->printName();
// 输出结果
// Join
// B Class
大家可以在项目中自行挖掘使用场景,比如一个会员父类class Vip,下面两个子类分别是超级会员svip和年费会员yvip,可以在两个子类中分别重写static usergroup()方法或者其他静态属性,父类中使用延迟静态绑定,这样可以写出很优雅的代码。