PHP的继承方法如何获取子类名?get_class() 和 get_called_class()

PHP里的__CLASS__这类东西是静态绑定的,如果不在子类里重载的话,那么继承父类方法所得到的依旧是父类的名称,而不是子类的名称,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class A
{
    function __construct()
    {
        echo __CLASS__;
    }
 
    static function name()
    {
        echo __CLASS__;
    }
}
 
class B extends A
{
}
 
$objB = new B(); // 输出 A
B::name();       // 输出 A

此时,无论将B实例化还是直接调用静态方法,echo出来的都会是A。

 

而实际上我想要得到的是子类B的名称!那如何实现呢?

PHP自带两个函数 get_class()get_called_class() 可以解决这个问题。

get_class()用于实例调用,加入参数($this)可解决子类继承调用的问题,而get_called_class()则是用于静态方法调用。

需要注意的是get_called_class()需要 PHP>=5.3.0 才支持,官方手册:http://php.net/manual/en/function.get-called-class.php,对于 PHP5.3.0以下的版本,有人给出了如下实现方式:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
if (!function_exists('get_called_class'))
{
    class classTools
    {
        private static $i = 0;
        private static $file = null;
 
        public static function get_called_class()
        {
            $bt = debug_backtrace();
 
            // 使用 call_user_func 或 call_user_func_array 函数调用类方法,处理如下
            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'))
            )
            {
                // 如果参数是数组
                if (is_array($bt[3]['args'][0]))
                {
                    $toret = $bt[3]['args'][0][0];
 
                    return $toret;
                }
                else if (is_string($bt[3]['args'][0]))
                {
                    // 如果参数是字符串
                    // 如果是字符串且字符串中包含::符号,则认为是正确的参数类型,计算并返回类名
                    if (false !== strpos($bt[3]['args'][0], '::'))
                    {
                        $toret = explode('::', $bt[3]['args'][0]);
 
                        return $toret[0];
                    }
                }
            }
 
            // 使用正常途径调用类方法,如:A::make()
            if (self::$file == $bt[2]['file'] . $bt[2]['line'])
            {
                self::$i++;
            }
            else
            {
                self::$i = 0;
                self::$file = $bt[2]['file'] . $bt[2]['line'];
            }
            $lines = file($bt[2]['file']);
            preg_match_all('/([a-zA-Z0-9\_]+)::' . $bt[2]['function'] . '/', $lines[$bt[2]['line'] - 1], $matches);
 
            return $matches[1][self::$i];
        }
    }
 
    function get_called_class()
    {
        return classTools::get_called_class();
    }
}

现在,把例子修改下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class A
{
    function __construct()
    {
        echo get_class($this);
    }
 
    static function name()
    {
        echo get_called_class();
    }
}
 
class B extends A
{
}
 
$objB = new B(); // 输出 B
B::name();       // 输出 B

呵呵,这是我想要的结果!

 

 

延伸阅读:

PHP get_class 返回对象的类名

PHP get_class_methods函数用法

父类方法返回子类实例:PHP延迟静态绑定

posted @   52php  阅读(2657)  评论(1编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· 程序员常用高效实用工具推荐,办公效率提升利器!
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 【译】WinForms:分析一下(我用 Visual Basic 写的)
点击右上角即可分享
微信分享提示