2014-02-20 5 views
1

Я делал небольшой эксперимент с PHP-кланами, и я столкнулся с этой странной проблемой.Функция, вызывающая себя бесконечно?

Класс предназначен для назначения его $ экземпляра свойства экземпляра себя в случае $ экземпляра является нулевого, но этот механизм, который, как предполагается, чтобы предотвратить бесконечное чувство собственного деторождения, кажется, не в состоянии, и это что происходит:

Fatal error: Maximum function nesting level of '100' reached, aborting!

<?php 
class SeemsLikeInfinity { 

public $instance; 

public function __construct() { 

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

     $this->instance = new self; 

    } 
} 

} 

$looping = new SeemsLikeInfinity(); 

?> 

Почему это происходит? __construct просто создает новый экземпляр класса, который пуст, поэтому имеет пустой $ экземпляр и, следовательно, создает экземпляр снова, делая цикл бесконечным?

Большого спасибо

ответ

1

Когда вы делаете объект с «новым» ключевым словом, он вызывает конструктор. Если вы используете new self в конструкторе, он снова вызовет конструкцию. Вызов бесконечного цикла.

Новый экземпляр автоматически создается при использовании new, поэтому вам не нужно хранить что-то вроде $this->instance. Переменная $this: Ваш экземпляр.

Важно помнить, что каждый экземпляр класса имеет свою переменную $instance. Таким образом, он всегда будет пустым вниз.

Теперь, если вы пытаетесь сделать синглтон, вы на самом деле нужно сделать конструктор приватным:

private function __construct() {} 

Тогда нам нужно instance быть статической переменной:

static private $instance; 

Нет Нет можно создать новый объект, используя новое ключевое слово. Итак, мы должны обеспечить статическую функцию для создания экземпляра:

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

Теперь вы получаете новые экземпляры с помощью этого:

$x = SeemsLikeInfinity::newInstance(); 

Теперь будет только когда-либо один объект SeemsLikeInfinity, и вы можете всегда доступ это с SeemsLikeInfinity::newInstance()

+0

Спасибо, это была попытка реализовать шаблон Singleton, но я ошибался. Я знаю, что $ this представляет экземпляр текущего объекта, я пытался создать объект, доступ к которому можно было бы получить с помощью $ object-> instance-> doSomething(), в то время как экземпляр содержит экземпляр объекта $. – user3104270

+0

Обновлено, как правильно сделать синглтон. –

+0

Это также приведет к «Неустранимая ошибка: использование $ this, когда не в контексте объекта» Я считаю, что ... – CD001

2

Это произойдет, поскольку параметр param $ instance всегда равен нулю. Каждый раз, когда вы создаете новый объект внутри класса. Если вы хотите, инвентарь Синглтон вы должны изменить __construct к приватным и использовать один статический метод, чтобы создать только один объект

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 
+0

Возможно, я ошибаюсь - но это приведет к «Неустранимая ошибка: использование $ this, если не в контексте объекта» – CD001

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(); 

Как и в сторону, лучше всего использовать I «когда-либо найденный для Singletons создает оболочку управления сеансом, поскольку сеанс, по самой своей природе, имеет только один экземпляр.

 Смежные вопросы

  • Нет связанных вопросов^_^