Одна из трудноуловимых ошибок

В одном из проектов, которые я сопровождаю, обнаружилась одна мерзкая и трудноуловимая ошибка, связанная с использованием статических переменных внутри методов.

Рассмотрим простой пример PHP-кода:

[-]
View Code PHP
<?php
class A {
    public function __construct()
    {
        static $i = 0;
        ++$i;
        print $i . "\n";
    }
}

$a = new A();
$b = new A();
?>

Внимание, вопрос: что будет выведено на экран (очень хороший вопрос для собеседования)?

Правильный ответ:

[-]
View Code Text
1
2

Дело всё в том, что хоть экземпляра класса у нас два, но класс как код только один. Поэтому статическая переменная внутри конструктора тоже всего одна. А такие вот ошибки иногда бывает очень трудно отследить, особенно, если код написан для PHP4 и при использовании очень большой иерархии классов.

Код, подобный приведённому выше, отлично работает, когда имеется только один экземпляр класса; при появлении дополнительных экземпляров (особенно, если они создаются по какому-нибудь условию) приводит к трудноуловимым ошибкам.

Если всё же по каким-либо причинам нужно использовать статическую переменную внутри метода (может быть, статическая переменная класса будет лучшим выбором?), нужно использовать шаблон проектирования “Одиночка” (известный как Singleton):

[-]
View Code PHP
<?php
class A {
    public static function instance()
    {
        static $self = false;
        if (false === $self) {
            $self = new A();
        }

        return $self;
    }

    protected function __construct()
    {
        static $i = 0;
        ++$i;
        print $i . "\n";
    }

    public function __clone()
    {
        trigger_error("Все козлы!", E_USER_ERROR);
    }
}

$a = A::instance();
$b = A::instance();
?>
[-]
View Code Text
1

Документация PHP предлагает альтернативный метод создания Одиночек.

Добавить в закладки

Связанные записи

21
Апр
2009

Комментарии к статье «Статические переменные внутри метода»  »

К статье «Статические переменные внутри метода» комментариев пока нет. Не хотите ли стать первым?

Подписаться на RSS-ленту комментариев к статье «Статические переменные внутри метода» Trackback URL: http://blog.sjinks.org.ua/php/547-static-variable-inside-class-method/trackback/

Оставить комментарий к записи «Статические переменные внутри метода»

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, Вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя