功能无限地呼唤着自己?

时间:2014-02-20 00:03:14

标签: php loops constructor infinity

我正在做一些关于PHP clases的实验,我遇到了这个奇怪的问题。

该类旨在为其 $ instance 属性分配一个自身的实例,以防$ instance为 null ,但此机制是应该阻止无限的自我生育似乎失败了,这就是发生的事情:

  

致命错误:达到“100”的最大功能嵌套级别,正在中止!

<?php
class SeemsLikeInfinity {

public $instance;

public function __construct() {

    if ( $this->instance == null ) {

        $this->instance = new self;

    }
}

}

$looping = new SeemsLikeInfinity();

?>

为什么会这样? __construct只是创建一个空的新实例,因此具有空 $ instance ,因此再次创建实例,使循环变为无限?

非常感谢

3 个答案:

答案 0 :(得分:2)

发生这种情况,因为param $ instance总是为null。每次在类中创建新对象。如果你想要实现单例,你应该将__construct更改为private并使用一个静态方法来创建一个对象

 class SeemsLikeInfinity {

   private static $instance;

   private function __construct() {
       // some action;
   }
   public static function generate_singleton(){
     if ( self::$instance == null ) {
         self::$instance = new self;
     }
     return self::$instance
   }
}

$singleton = SeemsLikeInfinity::generate_singleton();
// here you have singleton and you cant create more tha one object

答案 1 :(得分:1)

使用'new'关键字创建对象时,它会调用构造函数。如果在构造函数中使用new self,它将再次调用构造。导致无限循环。

使用new时会自动生成新实例,因此您无需存储$this->instance之类的内容。变量$this 您的实例。

要记住的重要一点是,类的每个实例都有自己的变量$instance。因此,它将始终为零。

现在,如果你想创建一个单例,你实际上必须将构造函数设为私有:

private function __construct() {}

然后我们需要instance作为静态变量:

static private $instance;

没有人可以使用new关键字创建新对象。那么我们需要提供一个静态函数来创建一个实例:

static function newInstance() {
    if ( self::instance == null ) {
        self::instance = new self;
    }
    return self::instance;
}

现在使用它来获取新实例:

$x = SeemsLikeInfinity::newInstance();

现在只有一个SeemsLikeInfinity对象,您始终可以使用SeemsLikeInfinity::newInstance()

访问它

答案 2 :(得分:0)

您必须使用静态变量而不是$this的原因是$this仅与当前对象相关 - 每次创建新的SeemsLikeInfinity对象时,您创建的是该对象的新$this - 因此,当您实例化该类时,$this->instance始终为null

那么,你的构造函数中发生了什么:

if ( $this->instance == null ) {
  $this->instance = new self;
}

...是一个新的$this->instance(没有指定的值)是在构造对象时创建的,所以用新的$this->instance构造一个新对象,同样没有值,所以一个新的对象是用新的$this->instance构造的,同样没有值...等等,永远。

然而,静态变量与类本身有关...您可以根据需要多次实例化该类,并且每个创建的对象都将继承该类中静态变量的最后设置值。

你要做的是创建一个Singleton,这样你就不会直接调用构造函数,通过静态getInstance()方法实例化和访问类:

// I've made this a "final" class - you can't really
// extend Singletons without getting into a mess
final class SeemsLikeInfinity {

  // this needs to be a static variable as it'll
  // be checked from the static self::getInstance() method
  // it should also be private as you'll never call it from
  // outside the class
  private static $instance;

  // the constructor function should also be private
  // as it'll ONLY ever be called from the 
  // self::getInstance() method
  private function __construct() {
    // ... do stuff here to instantiate your class
  }

  // Singletons can't be cloned
  public function __clone() {
    throw new Exception("ERROR : you can't clone Singletons", E_USER_ERROR);
  }

  // this is the main getInstance() method called
  // to actually instantiate or call the class
  public static function getInstance() {
    if(!self::$instance) { self::$instance = new self(); }
    return self::$instance;
  }
}

// now, to instantiate or access your class you'd use getInstance()
// you'll no longer have permanently reiterating classes and you
// should be golden
$looping = SeemsLikeInfinity::getInstance();

顺便说一句,我发现Singletons的最佳用途是构建一个会话管理包装器,因为一个会话本质上只有一个实例。