Отметил для себя необычное поведение статических свойств в экземплярах класса есть код:
class A{
public static $key=0;
public function getKey(){
return self::$key;
}
}
class B extends A {}
A::$key = 1;
$b = new B();
echo $b->getKey();
Здесь все понятно мы изменили статическое свойство класса A::$key = 1; со стороны клиента. И после этого любой экземпляр класса А или наследник этого класса (в данном случае В) будет иметь измененное значение статического свойства $key
Но следующий код мне стал непонятным - в нижеприведенном коде мы изменили статическое свойство экземпляра класса, что автоматически затронуло статическое свойство класса. Это что ? - некая глобальная переменная в рамках всех наследников этого класса? Вот код
<?php
class A{
protected static $key=0;
public function plus(){
++self::$key;
}
public function getKey(){
return self::$key;
}
}
class B extends A {}
$a = new A();
echo $a->getKey().'</br>';
$a->plus();
echo $a->getKey().'</br>';
$b = new B();
echo $b->getKey().'</br>';
выдал
0
1
1
Вот еще код
<?php
class A{
protected static $key=0;
public function plus(){
++self::$key;
}
public function getKey(){
return self::$key;
}
}
class B extends A {}
$a = new A();
echo $a->getKey().'</br>';
$b = new B();
$a->plus();
echo $a->getKey().'</br>';
echo $b->getKey().'</br>';
выдал
0
1
1
в итоге любое изменение статического свойства в любом наследнике меняет автоматически статическое свойство во ВСЕХ экземплярах - наследниках. Это ж альтернатива глобальным переменным или я чего то не понимаю и почему то об этом в учебниках не пишут.
на основе слов @perfect
поставил эксперимент
<?php
class A{
protected static $key=0;
public function plus(){
++self::$key;
}
public function getKey(){
return self::$key;
}
}
class B extends A {}
class C extends A {}
$b = new B();
$c = new C();
$b->plus();
echo $c->getKey().'</br>';
выдал
1
в итоге у них глобальная видимость - где бы экземпляры классов не находились
Но это еще не все, как показа практика @chernomyrdin обращаясь к одной и той же статической переменной - можно обращаться к различным участкам оперативной памяти. В итоге "в одной и той же переменной" могут храниться разные значения
<?php
class A {
protected static $key=0;
public function getGlobalKey(){
return self::$key;
}
//применяем позднее статическое связывание
public function getCurrentKey(){
return static::$key;
}
public function plusGlobalKey(){
++self::$key;
}
//применяем позднее статическое связывание
public function plusCurrentKey(){
++static::$key;
}
}
class B extends A{
protected static $key=0;
}
class C extends B{}
$a = new A();
$a->plusGlobalKey();
$b = new B();
echo $a->getCurrentKey().'<br/>';
echo $b->getCurrentKey().'<br/>';
echo $b->getGlobalKey().'<br/>';
$a->plusGlobalKey();
echo '<hr/>';
echo $a->getCurrentKey().'<br/>';
echo $b->getCurrentKey().'<br/>';
echo $b->getGlobalKey().'<br/>';
$b->plusCurrentKey();
echo '<hr/>';
echo $a->getCurrentKey().'<br/>';
echo $b->getCurrentKey().'<br/>';
echo $b->getGlobalKey().'<br/>';
echo '<hr/>';
$c = new C();
echo $c->getCurrentKey().'<br/>';
echo $c->getGlobalKey().'<br/>';
выводит
1
0
1
-----------------
2
0
2
-----------------
2
1
2
-----------------
1
2
Резюме: @perfect - объяснил почему так происходит
@chernomyrdin - подтолкнул к теме позднего статического связывания - в последнем примере я как раз понял как оно работает
Важно понять, что статические свойства общие
для всех экземпляров класса и существуют в единичном
виде (такие поля хранит сам класс). Каждое изменение каким либо экземпляром класса статического свойства отражается на всех остальных экземплярах.
В вашем случае вы один раз выполнили функцию $a->plus(); и с нуля у вас получилась единица в обоих экземплярах.
Что бы вы достаточно смогли разобраться я нарисовал картинку объясняющую принцип хранения статистических переменных внутри памяти.
Область видимости статических переменных ограничена самим классом для защиты от внешнего изменения (в отличие от глобальных переменных) и используется для использования потомками только этого класса (например для обмена какой либо информацией)
Со статиками в PHP все сложно, начиная с того как к ним обращатся self::$key
и static::$key
причем поведение различное в 5.x и 7.0
Потом вот пример для размышления:
class A {
public function inc () {
static $value = 0;
return get_called_class() . '::' . ++$value;
}
}
class B extends A {}
$a = new A;
echo $a->inc(), "\n";
$b = new B;
echo $b->inc(), "\n";
echo $a->inc(), "\n";
echo $b->inc(), "\n";
$c = new A;
echo $c->inc(), "\n";
echo $c->inc(), "\n";
echo $a->inc(), "\n";
Результат работы:
A::1
B::1
A::2
B::2
A::3
A::4
A::5
Виртуальный выделенный сервер (VDS) становится отличным выбором
Сейчас на сайте, если происходит запрос к несуществующей статье или разделу текстом вывозится, что такой статьи или раздела не существует,...