素材牛VIP会员
[已解决]php中静态成员方法和静态成员变量是不是不支持多态?
 li***56  分类:PHP代码  人气:812  回帖:5  发布于6年前 收藏

各位大神好,我实现了一个日志工具基类,并派生了两个子类,一个是运维日志类,一个是业务日志类,并在基类中设置了一个静态变量希望能用以区分两个子类,但在调用静态方法时,实际上完全不是想象中的情况,代码如下:

// 日志工具基类
class LogTool
{
    protected static $type;
    
    public static function debug($msg) {
        switch (self::$type) {
        case 'biz':
            echo '把日志写入数据库表1';
            break;
        case 'opt':
            echo '把日志写入数据库表2';
            break;
        default:
            echo 'error';
        }
    }
    
    // 其他代码省略
}

// 运维日志类
class OptTool extends LogTool
{
    protected static $type = 'opt';
}

// 业务日志类
class BizTool extends LogTool
{
    protected static $type = 'biz';
}

// 调用代码
BizTool::debug('王小虎已登录');

代码如上,实际上函数 dosomething 的运行情况是每次都输出 'error',因为在执行静态方法debug时,静态成员 $type 是空值;
但是如果我把 debug 函数在子类中再实现一次,则运行时 $type 变量就是有值的。
可是这样做就完全没意义了,抽象父类出来就是为了减少重复代码的,现在两个子类除了写入日志的表不同,其他完全相同,结果这样的结果弄得我欲哭无泪。

恳请大神们指点一二,万分感谢!

 标签:php

讨论这个帖子(5)垃圾回帖将一律封号处理……

Lv6 码匠
zh***ni 职业无 6年前#1

给题主提供一个关键词后期静态绑定

<?php
//后期静态绑定
class Log {
    public static function debug($msg) {
        if (static::$type == 'biz') {
            return $msg;
        } elseif (static::$type == 'opt') {
            return $msg;
        }
    }
}
class Opt extends Log {
    public static $type = 'opt';

}

class Biz extends Log {
    public static $type = 'biz';
}

echo Opt::debug('ooopppttt') . PHP_EOL;
echo Biz::debug('bbbiiizzz') . PHP_EOL;
Lv5 码农
me***20 技术总监 6年前#2

额,我自己的研究过程还是略掉,不出来丢人现眼了,不过有个问题得弄弄清楚,就是为啥这样子的代码运行时会报错呢,是不是抽象函数不是这样子用的?

abstract class LogTool
{
    protected static $type;

    public static function debug($msg)
    {
        $type = STATIC::getType();
        switch ($type) {
            case 'biz':
                echo '把日志写入数据库表1';
                break;
            case 'opt':
                echo '把日志写入数据库表2';
                break;
            default:
                echo 'error';
        }
    }

    // 其他代码省略
    abstract protected static function getType();
}

// 运维日志类
class OptTool extends LogTool
{
    protected static function getType() {
        return self::$type;
    }

    protected static $type = 'opt';
}

// 业务日志类
class BizTool extends LogTool
{
    protected static function getType() {
        return self::$type;
    }

    protected static $type = 'biz';
}

// 调用代码
BizTool::debug('王小虎已登录');

运行时报错 Strict standards: Static function LogTool::getType() should not be abstract in xxxx on line 28 ,但又能输出正确结果,不知作何解?

Lv3 码奴
风***灬 页面重构设计 6年前#3

基类中采用static::的方式,可以覆盖当前基类中定义的静态变量/方法,而去使用子类中定义的静态变量/方法

提供两个链接关于static::(后期静态绑定(Late Static Binding))的介绍和使用说明。

后期静态绑定--来自php官方手册
php静态变量-- 有明 的回答

Lv7 码师
封***榜 职业无 6年前#4
<?php
class LogTool
{

    public static function debug($msg) {
        switch (static::TYPE) {
            case 'biz':
                echo 'biz';
                break;
            case 'opt':
                echo 'opt';
                break;
            default:
                echo 'error';
        }
    }
}

// 运维日志类
class OptTool extends LogTool
{

    const TYPE = 'opt';
}

// 业务日志类
class BizTool extends LogTool
{
    const TYPE = 'biz';
}

BizTool::debug('王小虎已登录');
OptTool::debug('王小虎又登录了');
Lv3 码奴
空***子 职业无 6年前#5

因为你用的是self::$type, self表示这个关键字所在类的类名.

翻译一下就是self::$type === LogTool::$type

所以不可能调用到子类上面的.

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取