PHP7.3:如何在不使它在子类中重新声明的情况下,以最窄的范围继承一个受保护的静态属性?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP7.3:如何在不使它在子类中重新声明的情况下,以最窄的范围继承一个受保护的静态属性?相关的知识,希望对你有一定的参考价值。

在我正在处理的应用程序中,MVC堆栈的Model部分旨在通过单例工作;每个模型都有一个__getInstanceMethod,它是

protected static $singleton;
public static function __getInstance(): self {
    if(self::$singleton === null) {
        self::$singleton = __CLASS__;
        self::$singleton = new self::$singleton;
    }
    return self::$singleton;
}

最终结果是,如果在同一Model类上两次调用__getInstance(),它将两次都返回相同的精确对象。

我试图通过这样编辑__getInstance()方法到模型的父类BaseModel来减少代码重复,

class BaseModel {
    protected static $singleton;
    public static function __getInstance(): self {
        if (static::$singleton === null) {
            static::$singleton = __CLASS__;
            static::$singleton = new static::$singleton();
        }
        return static::$singleton;
    }
}
class AModel extends BaseModel {
    protected static $singleton;
    /** ... */
}
class BModel extends BaseModel {
    protected static $singleton;
    /** ... */
}

AModel::__getInstance(); // AModel
BModel::__getInstance(); // BModel

问题是,我需要为每个Model类手动添加$ singleton属性,否则,我将始终返回我调用该方法的第一个Model类的实例。

class BaseModel {
    protected static $singleton;
    public static function __getInstance(): self {
        if (static::$singleton === null) {
            static::$singleton = __CLASS__;
            static::$singleton = new static::$singleton();
        }
        return static::$singleton;
    }
}
class AModel extends BaseModel {}
class BModel extends BaseModel {}

AModel::__getInstance(); // AModel
BModel::__getInstance(); // Still AModel

有没有一种方法可以避免这样做?

答案

您可以切换到“ instance map”,例如:

<?php
declare(strict_types=1);

error_reporting(-1);
ini_set('display_errors', 'On');

class BaseModel
{
    protected static $instances = [];

    public static function __getInstance(): self
    {
        if (!isset(static::$instances[static::class])) {
            static::$instances[static::class] = new static();
        }

        return static::$instances[static::class];
    }
}

class AModel extends BaseModel
{
}

class BModel extends BaseModel
{
}

echo get_class(AModel::__getInstance()), "\n";
echo get_class(BModel::__getInstance());

https://3v4l.org/qG0qJ

以上是关于PHP7.3:如何在不使它在子类中重新声明的情况下,以最窄的范围继承一个受保护的静态属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使当前视图颤动的情况下实现这种幻灯片效果

如何在不使它们不可变的情况下使 python 数据类可散列?

如何在不使 main() 异步的情况下将异步对象注册到 get_it 包?

SQLAlchemy:如何在不使其成为主键的情况下使整数列 auto_increment (且唯一)?

如何在不使其全屏的情况下删除颤振闪屏状态栏的颜色覆盖?

Visual C++/Cli 中的异步睡眠,如何在不使 GUI 停止的情况下创建一个 X 毫秒来调用函数