Автозагрузка PHP и статическая переменная в функции
=== Base.php ===
<?php
class Base
{
public static function e()
{
static $number = 0;
$number++;
var_dump($number);
}
}
=== A.php ===
<?php
class A extends Base {}
=== B.php ===
<?php
class B extends Base {}
=== test.php ===
function __autoload($classname)
{
require_once("{$classname}.php");
}
Base::e();
A::e();
B::e();
php test.php, результат:
int(1)
int(2)
int(2)
Почему не результат 1,1,1?
Ответы
Ответ 1
Try
require "Base.php";
Base::e();
require "A.php";
A::e();
против.
require "Base.php";
require "A.php";
Base::e();
A::e();
Первое будет давать int(1) int(2)
, а последнее дает int(1) int(1)
.
Почему?
Когда класс привязан, содержимое переменной static
копируется именно в тот момент, каким оно является в настоящий момент. Нет резервной копии исходного значения статической переменной.
Это означает, что когда статическая переменная 0
, когда класс A
привязан, A::e()
будет иметь 0
как статическое значение; в случае, если 1
, A::e()
также будет иметь значение 1
.
Аналогично для B::e()
, тогда как Base::e()
и A::e()
независимы при копировании значений (без ссылок). Он также будет иметь ту же статическую переменную Base::e()
, которая имеет время привязки B
.
Ответ 2
Я провел некоторое исследование по этой проблеме, и это действительно странно.
Статические свойства внутри методов остаются их состоянием между экземплярами объекта. Это может сбить с толку. Также есть две статики: статическая функция, а другая - статическая переменная внутри метода.
Он может быть связан с автозагрузчиком. Я сделал аналогичный пример с вашим, но не использовал статические методы, но использовал статическую переменную внутри метода. Результат - 1:1: 1, используя как автозагрузчик, так и тот же файл.
<?php
class Base
{
public function t()
{
static $number = 0;
$number++;
var_dump($number);
}
public static function e()
{
static $number = 0;
$number++;
var_dump($number);
}
}
$base = new Base();
$base->t();
$a = new A();
$a->t();
$b = new B();
$b->t();
Также, если вы не выполнили Base::e()
, результат будет правильным.
Я сделал require_once без автозагрузки, и он все еще работает. Так что это определенно из-за автозагрузчика.
Если вы положили
require_once "Base.php";
require_once "A.php";
require_once "B.php";
вместо функции автозагрузчика он работает. Почему я не знаю, я пытался найти что-либо, рассматривая статические переменные с автозагрузчиком, но безуспешно. Однако этот ответ может дать вам некоторые подсказки.