Подтвердить что ты не робот

Какой смысл иметь $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?

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

Версия 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 happening here
        //if local variables hid properties, we'd have trouble
    }
}

В Java данный идентификатор может также представлять внутри той же функции локальную переменную и свойство, но:

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

Последствия

Из-за этих фактов было невозможно определить во время компиляции, если $var ссылается на локальную переменную или на свойство. Следовательно:

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

Ответ 3

PHP не был OOP.

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

Ответ 4

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