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?

16

Решение

Пытаться

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,

6

Другие решения

Я провел некоторое исследование по этой проблеме, и это действительно странно.

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

Это может быть связано с автозагрузчиком. Я сделал аналогичный пример с вашим, но без использования статических методов, но с использованием статической переменной внутри метода. Результат 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";

вместо функции автозагрузчика это работает. Почему я понятия не имею, я пытался найти что-то, рассматривая статические переменные с автозагрузчиком, но безуспешно. Тем не менее, этот ответ может дать вам некоторую подсказку.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector