PHP里的__CLASS__这类东西是静态绑定的,如果不在子类里重载的话,那么继承父类方法所得到的依旧是父类的名称,而不是子类的名称,比如:
01 | <?php |
02 | class A |
03 | { |
04 | function __construct() |
05 | { |
06 | echo __CLASS__ ; |
07 | } |
08 |
09 | static function name() |
10 | { |
11 | echo __CLASS__ ; |
12 | } |
13 | } |
14 |
15 | class B extends A |
16 | { |
17 | } |
18 |
19 | $objB = new B(); // 输出 A |
20 | B::name(); // 输出 A |
此时,无论将B实例化还是直接调用静态方法,echo出来的都会是A。
而实际上我想要得到的是子类B的名称!那如何实现呢?
PHP自带两个函数 get_class() 和 get_called_class() 可以解决这个问题。
get_class()用于实例调用,加入参数($this)可解决子类继承调用的问题,而get_called_class()则是用于静态方法调用。
注意,注意, 注意:虽说get_called_class()是用于静态方法调用,但它也可用于类的非静态方法中,但必须强调一点,get_called_class()所处的函数必须在类里面;
需要注意的是:get_called_class()需要 PHP>=5.3.0 才支持,官方手册:http://php.net/manual/en/function.get-called-class.php,对于 PHP5.3.0以下的版本,有人给出了如下实现方式:
01 | <?php |
02 | if (!function_exists( 'get_called_class' )) |
03 | { |
04 | class classTools |
05 | { |
06 | private static $i = 0; |
07 | private static $file = null; |
08 |
09 | public static function get_called_class() |
10 | { |
11 | $bt = debug_backtrace(); |
12 |
13 | // 使用 call_user_func 或 call_user_func_array 函数调用类方法,处理如下 |
14 | if ( array_key_exists (3, $bt ) && array_key_exists ( 'function' , $bt [3]) && in_array( $bt [3][ 'function' ], array ( 'call_user_func' , 'call_user_func_array' )) |
15 | ) |
16 | { |
17 | // 如果参数是数组 |
18 | if ( is_array ( $bt [3][ 'args' ][0])) |
19 | { |
20 | $toret = $bt [3][ 'args' ][0][0]; |
21 |
22 | return $toret ; |
23 | } |
24 | else if ( is_string ( $bt [3][ 'args' ][0])) |
25 | { |
26 | // 如果参数是字符串 |
27 | // 如果是字符串且字符串中包含::符号,则认为是正确的参数类型,计算并返回类名 |
28 | if (false !== strpos ( $bt [3][ 'args' ][0], '::' )) |
29 | { |
30 | $toret = explode ( '::' , $bt [3][ 'args' ][0]); |
31 |
32 | return $toret [0]; |
33 | } |
34 | } |
35 | } |
36 |
37 | // 使用正常途径调用类方法,如:A::make() |
38 | if (self:: $file == $bt [2][ 'file' ] . $bt [2][ 'line' ]) |
39 | { |
40 | self:: $i ++; |
41 | } |
42 | else |
43 | { |
44 | self:: $i = 0; |
45 | self:: $file = $bt [2][ 'file' ] . $bt [2][ 'line' ]; |
46 | } |
47 | $lines = file( $bt [2][ 'file' ]); |
48 | preg_match_all( '/([a-zA-Z0-9\_]+)::' . $bt [2][ 'function' ] . '/' , $lines [ $bt [2][ 'line' ] - 1], $matches ); |
49 |
50 | return $matches [1][self:: $i ]; |
51 | } |
52 | } |
53 |
54 | function get_called_class() |
55 | { |
56 | return classTools::get_called_class(); |
57 | } |
58 | } |
现在,把例子修改下:
01 | <?php |
02 | class A |
03 | { |
04 | function __construct() |
05 | { |
06 | echo get_class( $this ); |
07 | } |
08 |
09 | static function name() |
10 | { |
11 | echo get_called_class(); |
12 | } |
13 | } |
14 |
15 | class B extends A |
16 | { |
17 | } |
18 |
19 | $objB = new B(); // 输出 B |
20 | B::name(); // 输出 B |
呵呵,这是我想要的结果!
转载出处:http://blog.snsgou.com/post-874.html?utm_source=tuicool