后期静态绑定


Late static binding

我遇到了一个小问题。这是:

  1. 这是我的单例抽象类:

    abstract class Singleton {
    protected static $_instance = NULL;
    /**
     * Prevent direct object creation
     */
    final private function  __construct()
    {
        $this->actionBeforeInstantiate();
    }
    /**
     * Prevent object cloning
     */
    final private function  __clone() { }
    /**
     * Returns new or existing Singleton instance
     * @return Singleton
     */
    final public static function getInstance(){
        if(null !== static::$_instance){
            return static::$_instance;
        }
        static::$_instance = new static();
        return static::$_instance;
    }
    abstract protected function  actionBeforeInstantiate();
    }
    
  2. 之后,我创建了一个抽象注册表类:

    abstract class BaseRegistry extends Singleton
    {
        //...
    }
    
  3. 现在是会话注册的时候了。

    class BaseSessionRegistry extends BaseRegistry
    {
    //...
    protected function actionBeforeInstantiate()
    {
        session_start();
    }
    }
    
  4. 最后一步:

    class AppBaseSessionRegistryTwo extends BaseSessionRegistry { //... }
    class AppBaseSessionRegistry extends BaseSessionRegistry { //... }
    
  5. 测试

    $registry = AppBaseSessionRegistry::getInstance();
    $registry2 =AppBaseSessionRegistryTwo::getInstance();
    echo get_class($registry) . '|' . get_class($registry2) . '<br>';
    

输出:

AppBaseSessionRegistry|AppBaseSessionRegistry

我的期望是:

AppBaseSessionRegistry|AppBaseSessionRegistryTwo

为什么我会得到这样的结果?我该如何重新制作代码以获得预期的结果?

更新:我在我的框架中使用了这个。用户将扩展我的BaseSessionRegistry类并添加他们的内容。我想在我的框架类

中解决这个问题

您需要这样做:

class AppBaseSessionRegistryTwo extends BaseSessionRegistry {
    protected static $_instance = NULL;
    // ...
}
class AppBaseSessionRegistry extends BaseSessionRegistry { 
    protected static $_instance = NULL;
    //... 
}

如果不单独声明静态属性,它们将共享其父级的相同静态属性。

更新:如果您不希望子级声明静态属性,那么您可以将静态属性声明为父级的数组。

abstract class Singleton {
  protected static $_instances = array();
  // ...
  /**
   * Returns new or existing Singleton instance
   * @return Singleton
   */
  final public static function getInstance(){
    $class_name = get_called_class();
    if(isset(self::$_instances[$class_name])){
        return self::$_instances[$class_name];
    }
        return self::$_instances[$class_name] = new static();
    }
   abstract protected function  actionBeforeInstantiate();
}

您的第一行:

$registry = AppBaseSessionRegistry::getInstance();

将用CCD_ 3实例填充CCD_。在您的下一行$registry2 =AppBaseSessionRegistryTwo::getInstance();中,受保护的静态$_instance已经有了一个值,该实例将被返回。

一般来说,辛格尔顿和静力学是邪恶的。把它们结合在一起太可怕了。从事良好的OO编程,避免使用Singleton和statics。

 $registry = AppBaseSessionRegistry::getInstance();

上面的语句使用类AppBaseSessionRegistry的对象设置$_instance
由于在getInstance方法中,我们正在检查它之前是否已设置,因此返回因此您的第二个报表的值

$registry2 =AppBaseSessionRegistryTwo::getInstance();

getInstance将返回类AppBaseSessionRegistry的对象,即引用同一对象的$registry1和registry2