Какой смысл иметь $ this и self :: в PHP?

Почему PHP требует от вас явно писать $this ? Я бы понял, если бы вам пришлось использовать $this здесь:

 function foo($bar) { $this->bar = $bar; } 

Но вы должны написать это явно в подробном коде, который выглядит так:

 $this->var3 = globalFun($this->var, $this->var2[$this->anotherVar], $this->method()); 

в отличие от:

 $var3 = globaFun($var, $var2[$anotherVar], method()); 

Так в чем смысл $this ?

Дополнительный бонусный вопрос:

Почему мы должны различать статические ссылки и экземпляры? Зачем нам нужно:

 static function getValue() { return self::value; } 

Не удается ли PHP узнать во время выполнения, если рассматриваемая переменная / метод статична? Теперь, если я хочу изменить метод от статического до нестатического, я должен заменить все эти self:: на $this-> (и наоборот).

Не было бы лучше, если бы у нас было такое $this которое ведет себя так же, как на Java?

Solutions Collecting From Web of "Какой смысл иметь $ this и self :: в PHP?"

Хорошо, давайте удалим необходимость писать $this всюду. Взгляните на эту ситуацию:

 class Foo { public function setBar($value) { $bar = $value; } } $foo = new Foo(); $foo->setBar('some value'); 

Является ли $bar локальной переменной или членом $foo ?

Должна быть какая-то дифференциация. Они могли бы разрешить объявление локальных переменных с ключевым словом var , но это не было бы обратной совместимостью и было бы очень запутанным для людей, обновляющих старые версии PHP.

То же самое относится и к self:: Как интерпретатор знает, является ли функция, которую вы хотите вызвать, глобальной или конкретной для класса?

Поскольку это было вновь открыто, я отправлю здесь свой ответ , как и обещал.

Версия 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 ссылается на локальную переменную или на свойство. Вследствие этого:

  • Во время выполнения каждый раз, когда произошла переменная, он должен был сначала искать в локальной таблице символов, затем в таблице свойств экземпляра и, наконец, в списке статических свойств или в любом другом порядке (поскольку не может быть экземпляр и статическое свойство с тем же именем и статическими свойствами должно быть объявлено, здесь будет некоторый потенциал оптимизации, но точка стоит). Это означает, что символ в худшем случае должен быть поднят в трех разных местах. Это плохо с точки зрения производительности.
  • Такое появление символа может означать разные вещи в разных случаях. Это рецепт катастрофы.

PHP не был ООП.

Теперь это, но с побочными эффектами.

На самом деле, я знаю людей, которые используют это. в Java даже там, где это не нужно, потому что они считают, что он создает более четкий код;) У меня нет определенного ответа, но я полагаю, что внутренне получение $ var всегда должно быть переведено в $ this-> var. Поэтому не похоже, что кто-то намеренно усложнил ситуацию, заставив нас делать $ this-> var, но просто решил не реализовывать ярлык $ var. Если это помогает, я не знаю;)