PHP7.3:如何在不在子 class 中声明的情况下继承具有最严格范围的受保护静态 属性?
PHP7.3: How can I inherit a protected static property with the thightest possible scope without redeclaring it in the child class?
在我正在处理的应用程序中,MVC 堆栈的模型部分设计为通过单例工作;每个模型都有一个 __getInstanceMethod 即
protected static $singleton;
public static function __getInstance(): self {
if(self::$singleton === null) {
self::$singleton = __CLASS__;
self::$singleton = new self::$singleton;
}
return self::$singleton;
}
最终结果是,如果 __getInstance() 在同一个模型 class 上被调用两次,它两次都 returns 完全相同的对象。
我试图通过将 __getInstance() 方法移动到模型的父 class BaseModel 来减少代码重复,方法是像这样编辑它。
class BaseModel {
protected static $singleton;
public static function __getInstance(): self {
if (static::$singleton === null) {
static::$singleton = static::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
问题是,我需要为每个模型 class 手动添加一个 $singleton 属性,否则我将始终返回第一个模型的实例 class我调用了这个方法。
class BaseModel {
protected static $singleton;
public static function __getInstance(): self {
if (static::$singleton === null) {
static::$singleton = static::$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());
在 7.4+ 中可以简化为:
<?php
declare(strict_types=1);
error_reporting(-1);
ini_set('display_errors', 'On');
class BaseModel
{
private static array $instances = [];
public static function __getInstance(): self
{
return static::$instances[static::class] ??= new static();
}
}
在我正在处理的应用程序中,MVC 堆栈的模型部分设计为通过单例工作;每个模型都有一个 __getInstanceMethod 即
protected static $singleton;
public static function __getInstance(): self {
if(self::$singleton === null) {
self::$singleton = __CLASS__;
self::$singleton = new self::$singleton;
}
return self::$singleton;
}
最终结果是,如果 __getInstance() 在同一个模型 class 上被调用两次,它两次都 returns 完全相同的对象。
我试图通过将 __getInstance() 方法移动到模型的父 class BaseModel 来减少代码重复,方法是像这样编辑它。
class BaseModel {
protected static $singleton;
public static function __getInstance(): self {
if (static::$singleton === null) {
static::$singleton = static::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
问题是,我需要为每个模型 class 手动添加一个 $singleton 属性,否则我将始终返回第一个模型的实例 class我调用了这个方法。
class BaseModel {
protected static $singleton;
public static function __getInstance(): self {
if (static::$singleton === null) {
static::$singleton = static::$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());
在 7.4+ 中可以简化为:
<?php
declare(strict_types=1);
error_reporting(-1);
ini_set('display_errors', 'On');
class BaseModel
{
private static array $instances = [];
public static function __getInstance(): self
{
return static::$instances[static::class] ??= new static();
}
}