На http://php.net/manual/en/language.operators.precedence.php веб-страница, второй самый высокий уровень приоритета содержит левоассоциативный оператор, называемый [
,
Я не понимаю этого. Это [
используется для доступа / изменения записей массива, как в $myArray[23]
? Я не могу представить ни одного фрагмента кода, где нам нужно было бы знать «приоритет» этого по сравнению с другими операторами или где «ассоциативность» [
было бы полезно.
Это очень актуальный вопрос.
Во-первых, никогда не возникает двусмысленности в отношении того, что PHP должен оценивать первым, глядя на
правая сторона [
, так как скобка требует закрывающей, чтобы идти с ним, и так
каждый оператор между ними имеет приоритет над открывающей скобкой.
Пример:
$a[1+2]
+
имеет приоритет, то есть первый 1 + 2 должен быть оценен, прежде чем PHP сможет определить, какие
элемент для извлечения из $ а.
Но список приоритетов операторов не об этом.
Во-вторых, существует порядок оценки последовательных пар []
, как здесь:
$b[1][2]
PHP сначала оценит $b[1]
а затем применить [2]
к этому. Это слева направо
оценка и то, что предназначено для левая ассоциативность.
Но речь идет не столько об ассоциативности, сколько о приоритетности по отношению к другим операторам.
В списке говорится, что clone
а также new
операторы имеют приоритет над [
и это нелегко проверить.
Прежде всего, большинство конструкций, где вы бы объединить new
с квадратными скобками считаются недействительными
синтаксис. Например, оба эти утверждения:
$a = new myClass()[0];
$a = new myClass[0];
выдаст ошибку разбора:
синтаксическая ошибка, неожиданно ‘[‘
PHP требует, чтобы вы добавили скобки, чтобы сделать синтаксис действительным. Таким образом, мы не можем проверить
правила приоритета, как это.
Но есть и другой способ, используя переменную, содержащую имя класса:
$a = new $test[0];
это является правильный синтаксис, но теперь задача состоит в том, чтобы создать класс, который создает что-то
это действует как массив.
Это не тривиально, поскольку на свойство объекта ссылаются так: obj->prop
не
лайк obj["prop"]
, Однако можно использовать ArrayObject учебный класс которые могут иметь дело с квадратными скобками. Идея состоит в том, чтобы расширить этот класс и переопределить offsetGet метод чтобы убедиться, что только что созданный объект этого класса имеет возвращаемые элементы массива.
Чтобы сделать объекты пригодными для печати, я использовал магический метод __нанизывать, который выполняется, когда объект должен быть приведен к строке.
Итак, я придумал эту настройку, определив два похожих класса:
class T extends ArrayObject {
public function __toString() {
return "I am a T object";
}
public function offsetGet ($offset) {
return "I am a T object's array element";
}
}
class TestClass extends ArrayObject {
public function __toString() {
return "I am a TestClass object";
}
public function offsetGet ($offset) {
return "I am a TestClass object's array element";
}
}
$test = "TestClass";
С помощью этой установки мы можем протестировать несколько вещей.
echo new $test;
Это утверждение создает новый TestClass экземпляр, который затем должен быть преобразован в
строка, так что __нанизывать метод вызывается для этого нового экземпляра, который возвращает:
Я объект TestClass
Это как и ожидалось.
echo (new $test)[0];
Здесь мы начнем с тех же действий, поскольку скобки заставляют new
операция должна быть выполнена первой. На этот раз PHP не преобразует созданный объект в строку, а запрашивает у него элемент массива 0. На этот запрос отвечает offsetGet метод, и поэтому вышеприведенный оператор выводит:
Я элемент массива объекта TestClass
echo new ($test[0]);
Идея состоит в том, чтобы навязать противоположный порядок исполнения. К сожалению, PHP не позволяет этот синтаксис, поэтому придется разбить оператор на два, чтобы получить предполагаемый порядок оценки:
$name = $test[0];
echo new $name;
Так что теперь [
выполняется первым, принимая первый символ значения
$ тест, то есть «Т», а потом new
применяется к этому. Вот почему я
определил также T учебный класс. echo
звонки __нанизывать в этом случае, который дает:
Я объект Т
Теперь наступает последний тест, чтобы увидеть, какой порядок, когда нет скобок:
echo new $test[0];
Это правильный синтаксис, и …
Выход:
Я объект Т
На самом деле, PHP применил [
перед new
оператор, несмотря на то, что указано в
таблица приоритетов операторов!
clone
с new
clone
Оператор имеет похожее поведение в сочетании с [
, Достаточно странно, clone
а также new
не полностью равны с точки зрения правил синтаксиса. Повторение теста 2 с clone
:
echo (clone $test)[0];
выдает ошибку разбора:
синтаксическая ошибка, неожиданно ‘[‘
Но тест 4 повторяется с clone
показывает, что [
имеет приоритет над ним.
@bishop сообщил, что это воспроизводит давнюю ошибку документации # 61513: «clone
неправильный приоритет оператора.
Это просто означает, что переменная массива (левая ассоциативность — $ first) будет оценена перед ключом массива (правая ассоциативность — $ second)
$first[$second]
Это имеет большой смысл, когда массив имеет несколько измерений
$first[$second][$third][$fourth]
В PHP вы можете инициализировать пустые массивы с помощью []
поэтому, чтобы узнать, как определить массив, приоритет следующего символа определяет, как инициализировать массив.
Поскольку массивы являются частью синтаксической структуры, это делается перед любой математикой, по этой причине он просто имеет более высокий приоритет, чем другие вычислительные операторы.
var_dump([5, 6, 7] + [1, 2, 3, 4]); # 5674 - The array's must be known before applying the operator
Однако, честно говоря, я не совсем понимаю вопрос. В большинстве языков программирования [
и ]
связаны с массивами, являющимися частью базового синтаксиса, которые всегда имеют высокий приоритет (если не самый высокий)