Так как это было вновь открыто, я отправлю сюда мой ответ , как и обещал.
TL; версия DR Если бы не требовалось квалифицировать доступ к элементу, то были бы не только штрафы за производительность, но и одна и та же строка кода могла одновременно означать доступ к полю и доступ к локальной переменной, в зависимости от пути к коду.
Полная версия
В PHP всегда есть одна активная таблица символов за столом. Это либо глобальная таблица символов, либо таблица локальных символов функции / метода (которые, кстати, лениво строятся). Суперглобальные переменные и оптимизации, такие как скомпилированные переменные в стороне, когда запрашивается переменная $var
, она ищется в текущей таблице символов. Поскольку свойства объекта находятся не в таблицах символов, а в объектах (свойства экземпляра) или структуре, связанной с классом (статические свойства), поиск по $var
никогда не сможет вернуть свойство.
Чтобы перенести данную переменную в область действия функции, вы должны явно указать свое намерение, создав ссылку. Примеры:
$myglobal = 7;
class A {
private $prop;
public function meth() {
global $myglobal; //bring a global to the current scope
$prop =& $this->prop; //brings a property to the current scope
$local = 4;
$lambda = function () use (&$local) { };
}
}
Очевидно, это просто более изощренный способ выражения того, что происходит в настоящее время. Вопрос почему это поведение?
В конце концов, в Java мы должны набирать this.prop
только когда есть локальная переменная с именем prop
, скрывающая свойство. Почему это не очень хороший вариант для PHP?
Я могу придумать несколько причин.
Свойства объекта определяются во время выполнения
В PHP есть нечто, называемое "динамическими свойствами". Вы можете назначать новые свойства объектам во время выполнения. Фактически, при наличии двух объектов одного и того же класса один может иметь заданное свойство $a
, а другой - нет. Пример:
$obj1 = new stdClass();
$obj2 = new stdClass();
$obj1->a = 7;
В PHP определенные локальные переменные определяются во время выполнения
Переменные не должны быть объявлены; следовательно, в зависимости от пути кода, в какой-то момент переменная может быть или не быть определена. Чтобы добавить оскорбление ране, у нас также есть монстр, названный "переменными переменными". Пример:
class A {
private $g = 3;
public function func($varname) {
if (rand(1,2) == 1) {
$g = 4; //no block scope; the scope is the function's
}
$$varname = 5; //god knows what's happening here
//if local variables hid properties, we'd have trouble
}
}
В Java данный идентификатор может также представлять внутри той же функции локальную переменную и свойство, но:
- Не в одном и том же блоке (в PHP все блоки в функции имеют одинаковую область видимости).
- Вы получаете предупреждение, если скрываете собственность.
- Важно отметить, что в любом конкретном случае идентификатора это либо свойство, либо локальная переменная , иногда он не может быть один и другой раз другим.
Последствия * * тысяча пятьдесят один
Из-за этих фактов было бы невозможно определить во время компиляции, если $var
ссылается на локальную переменную или свойство. Следовательно:
Во время выполнения каждый раз, когда возникала переменная, она должна была бы искать сначала в локальной таблице символов, затем в таблице свойств экземпляра и, наконец, в списке статических свойств или в любом другом порядке (так как не может быть экземпляром, и необходимо объявить статическое свойство с тем же именем и статическими свойствами, здесь был бы некоторый потенциал оптимизации, но точка зрения остается в силе). Это означает, что символ в худшем случае придется искать в трех разных местах. Это плохо с точки зрения производительности.
Данное появление символа может означать разные вещи в разных случаях. Это рецепт катастрофы.