Подтвердить что ты не робот

PHP и статические переменные в объектных функциях

До сегодняшнего дня я думал, что у меня довольно хорошее понимание того, как работает статический модификатор. Я знаю, что (в терминах laymans) статическая переменная в функции не "reset" через вызовы этой функции, и я знаю, что статические переменные и функции в классе доступны, вызывая их через сам класс (не экземпляр класса).

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

Например:

class A {
    public function GetValue() {
        static $value = 0;
        $value++;
        return $value;
    }
}

$instance_1 = new A();
$instance_2 = new A();
echo $instance_1->GetValue();
echo $instance_1->GetValue();

echo $instance_2->GetValue();
echo $instance_2->GetValue();

echo $instance_1->GetValue();
echo $instance_1->GetValue();

Обратите внимание, что функция GetValue не объявляется как статическая или не используется статическим образом (как, например, в самом классе).

Теперь я всегда предполагал, что это будет выводить: 121234

Вместо этого я обнаружил, что он выведет: 123456

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

Я думаю, мой вопрос двоякий, затем... 1) это ошибка или ожидаемое поведение? 2) используют ли другие языки эти "статические внутри нестатические" переменные одинаково или это уникально для PHP?

4b9b3361

Ответ 1

  • Ожидается.
  • Это также относится к С++ (и, возможно, к другим).

Вы должны думать о нестатических функциях членов класса, как если бы они были похожими на обычные функции, но с неявным аргументом $this, который автоматически предоставляется интерпретатором. (Это точно, как они реализованы на большинстве языков.)

Ответ 2

Я скопировал следующую информацию из этой статьи Josh Duck: http://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/

Статические переменные доступны с PHP 4 и позволяют вам определять постоянную переменную, доступную только из текущей функции. Это позволяет инкапсулировать состояние в функцию или метод и может устранить необходимость в классах, где будет достаточно одной функции.

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

Статические переменные can not сохраняют область вызывающего класса. Это может быть потенциально проблематичным, если у вас есть унаследованный метод, содержащий статическую переменную, вызываемую как внутри, так и вне ее класса.

Ответ 3

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