All streams
Search
Write a publication
Pull to refresh
8
0
Александр @torf

PHP программист

Send message
Она не теряет своего значения, B::i()!=C::i() (они наследуются от A, но переменные внутри методов имеют разное значение ($i1!=$i2)). Ну не может терять значение то, что никогда не было инициализировано. Проверьте var_dump'ом.
class A {
    public static function i(){
        static $i;
		var_dump($i);
        return $i? $i: $i = new static;
    }
    function say(){ echo get_class($this) . "\n"; }
}

class B extends A{}
class C extends A{}

B::i()->say();
C::i()->say();

/*
Вывод:
null
B

null
C 
*/


Я в прошлом комментарии описался, прошу прощения, естественно имел ввиду переменную $i внутри метода, а не свойство класса.
По-порядку (разбираю второй вариант):
1. Выполняем
B::i()

а). Т.к. $i — не присвоено значение, то при выполнении тернарного оператора NULL, при преобразовании в булев контекст будет равен FALSE. Следовательно $i=new static; Где static — это контекст класса B. Следовательно $i — экземпляр (объект)
класса B.
б). Функция $i->Say(), где $i — объект класса B совершенно логично выполнит get_class($this). Т.е. вернёт имя класса, к которому принадлежит $this — в данном случае B.
2. Выполняем
C::i()

а). Т.к. $i — не присвоено значение (то, что оно помечено статическим — ничего не значит, т.к. по сути B::i() и C::i() не зависят друг от друга в плане инициализации свойств), то при выполнении тернарного оператора NULL, при преобразовании в булев контекст будет равен FALSE. Следовательно $i=new static; Где static — это контекст класса C. Следовательно $i — экземпляр (объект)
класса C.
б). Функция $i->Say(), где $i — объект класса C совершенно логично выполнит get_class(). Т.е. вернёт имя класса, к которому принадлежит $this — в данном случае C.

Надеюсь это то, что вы хотели услышать
Извините, не вижу в этом коде, за исключением вышеупомянутых странностей, ничего необычного.
Поправьте меня, если я неправильно понял… Но получается не-статический метод вполне реально вызвать статически (с использованием ::)?
<?php
class A
{
	public function DynamicMethod()
	{
		var_dump(debug_backtrace());
		return 'I am Dynamic';
	}
}
echo A::DynamicMethod();
/*
Вывод:
array (size=1)
  0 => 
    array (size=6)
      'file' => string 'C:\OpenServer\domains\test1.ru\index.php' (length=40)
      'line' => int 11
      'function' => string 'DynamicMethod' (length=13)
      'class' => string 'A' (length=1)
      'type' => string '::' (length=2)
      'args' => 
        array (size=0)
          empty

I am Dynamic
*/
?>
Перевод: «Псевдо-переменная $this доступна в том случае, если метод был вызван в контексте объекта. $this является ссылкой на вызываемый объект. Обычно это тот объект, которому принадлежит вызванный метод, но может быть и другой объект, если метод был вызван статически из контекста другого объекта.»

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

Да, вот именно таблички и не хватает, а жаль. Серьёзно, для меня не было очевидным такое поведение $this. Но это обозначает лишь только, что есть куда развиваться.
Спасибо за разъяснения и приобретённый опыт. Сделаю выводы. Думаю многие, кто читает ваш комментарий и не знают этой особенности также приобретут новые знания. Но всё же, мне кажется, что разработчикам стоило бы задокументировать неочевидное поведение интерпретатора. Ведь если наперёд не знать, что это капризы PHP, то программист, в особенности новичок, может потратить не один час в тщетных поисках ошибки. Зная такую особенность, программисты смогут избегать, а ещё лучше, учитывать это при использовании такого рода конструкций.
Спасибо за верное замечание. Статью поправил.

Information

Rating
Does not participate
Location
Кубинка, Москва и Московская обл., Россия
Date of birth
Registered
Activity