@ Одинокий день , похоже, это в основном правильно. Однако, в частности, в связи с вашим последующим комментарием относительно наследования, поведение области действия статической переменной внутри функций выглядит более сложным. Я использую PHP 5.3.16 для всех моих примеров.
Сводка : поведение ключевого слова static
при использовании для определения области действия переменной в экземпляре функции, кажется, зависит от наследования и от того, где вы находитесь в стеке вызовов функций.
Вот несколько примеров.
Во-первых, это похоже на ваш первоначальный пример: создать экземпляр статической переменной в методе __construct()
класса, создать два экземпляра этого класса и посмотреть, как эта переменная ведет себя.
<?php
// Example 1
class A {
public function __construct() {
static $i = 0;
$i++;
$this->i = $i;
}
}
$o1 = new A();
$o2 = new A();
printf("\$o1->i: %d\n", $o1->i); // outputs "$o1->i: 1"
printf("\$o2->i: %d\n", $o2->i); // outputs "$o2->i: 2"
?>
Пока никаких сюрпризов. Переменная создается один раз (до 0), а затем увеличивается с каждым отдельным экземпляром.
Если вы расширяете класс A
как B
и создаете экземпляр одного из них (оставляя все остальное одинаковым), вы получаете такое же поведение:
<?php
// Example 2
class A {
public function __construct() {
static $i = 0;
$i++;
$this->i = $i;
}
}
class B extends A {}
$o1 = new A();
$o2 = new B();
printf("\$o1->i: %d\n", $o1->i); // outputs "$o1->i: 1"
printf("\$o2->i: %d\n", $o2->i); // outputs "$o2->i: 2"
?>
Еще раз, никаких сюрпризов. Давайте вернемся к первому примеру и немного подправим его. Сначала мы перемещаем вызов создания / инкремента статической переменной в метод-член. Обратите внимание, что я удалил класс B
для этого:
<?php
// Example 3
class A {
public function __construct() {
$this->setI();
}
public function setI() {
static $i = 0;
$i++;
$this->i = $i;
}
}
$o1 = new A();
$o2 = new A();
printf("\$o1->i: %d\n", $o1->i); // outputs "$o1->i: 1"
printf("\$o2->i: %d\n", $o2->i); // outputs "$o2->i: 2"
?>
Все тот же вывод.
Однако , когда вы расширяете A
как B
и оставляете ту же структуру на месте:
<?php
// Example 4
class A {
public function __construct() {
$this->setI();
}
public function setI() {
static $i = 0;
$i++;
$this->i = $i;
}
}
class B extends A {}
$o1 = new A();
$o2 = new B();
printf("\$o1->i: %d\n", $o1->i); // outputs "$o1->i: 1"
printf("\$o2->i: %d\n", $o2->i); // outputs "$o2->i: 1"
?>
Обратите внимание на вывод: во всех остальных случаях $o2->i
стало 2, кроме этого.
Так что, похоже, что если мы расширим A
и , переместим статическое создание экземпляра в метод экземпляра, мы теперь, похоже, представили новую область видимости для переменной $i
, тогда как во всех других случаях экземпляры имеют общую область видимости для этой статической переменной.
Еще более запутанно , рассмотрим этот пример; он идентичен предыдущему, но в этом случае класс B
получает собственную реализацию setI()
, которая просто уступает реализации своего родительского класса:
<?php
// Example 5
class A {
public function __construct() {
$this->setI();
}
public function setI() {
static $i = 0;
$i++;
$this->i = $i;
}
}
class B extends A {
public function setI() {
parent::setI();
}
}
$o1 = new A();
$o2 = new B();
printf("\$o1->i: %d\n", $o1->i); // outputs "$o1->i: 1"
printf("\$o2->i: %d\n", $o2->i); // outputs "$o2->i: 2"
?>
Как видите, $o2->i
теперь вернулся к значению 2, что мы получили почти везде (кроме примера № 4)
Это мне кажется очень нелогичным. Я ожидаю, что или разные экземпляры получат свои собственные области действия для этой переменной, или все экземпляры (включая экземпляры расширенных классов) имеют одну и ту же область видимости.
Я не могу сказать, является ли это ошибкой в PHP, или это ожидаемое поведение. Документы PHP по области действия статических переменных говорят:
Статическая переменная существует только в локальной области функций, но она не теряет своего значения, когда выполнение программы выходит из этой области.
Они не вдавались в подробности того, как определяется «область действия функции» в контексте экземпляров объекта, поэтому я не уверен, ожидается ли крайний случай в Примере № 4 или нет.