Предварительно объявить все частные / локальные переменные?

Это может быть основной вопрос, но это заставило меня задуматься довольно долгое время.

Должен ли я объявлять все частные / локальные переменные частным? Или это необходимо только для «важных» переменных?

Например, у меня есть (временный) результат вычисления. Должен ли я предварительно объявить эту переменную?

Надеюсь, кто-то может это указать.

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

То же самое относится к объектам (свойствам), поскольку они являются переменными всего объекта. Поэтому они должны быть определены в классе уже (по умолчанию их значение NULL в PHP). Динамические значения / фильтрация могут выполняться в методах конструктора и / или сеттера.

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

И, возможно, помните, что в PHP вы можете получить доступ к приватным свойствам из одного класса – не только к одному и тому же объекту. Это может быть полезно знать, потому что это позволяет вам сохранять личные вещи немного дольше.

Например, у меня есть (временный) результат вычисления. Должен ли я предварительно объявить эту переменную?

Обычно это локальная переменная в функции или методе. Он определяется, когда он получает возвращаемое значение метода расчета. Поэтому нет необходимости предварительно объявлять его (per-se).

 ... function hasCalculation() { $temp = $this->calculate(); return (bool) $temp; } ... 

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

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

Поскольку вы говорите о private , protected и public я так понимаю, вы говорите о свойствах , а не о переменных.
В этом случае: да , вы должны объявить их заранее.

Из-за того, как разрабатываются объекты PHP, во время компиляции создается массив ( properties_table ). Этот массив гарантирует, что доступ к данному свойству будет как можно быстрее. Однако, если вы добавляете свойства по мере продвижения, PHP также должен отслеживать это. По этой причине у объекта также есть простая таблица properties .
В то время как первый ( properties_table ) представляет собой массив указателей, последний представляет собой простую таблицу ключей => значение.
И что? Хорошо, потому что properties_table содержит только указатели (которые имеют фиксированный размер), они хранятся в простом массиве, а указатели выбираются с использованием соответствующих смещений. Смещения сохраняются в еще одной HashTable, которая является указателем ce->properties_info .

Как заметил мне bwoebi в комментариях: получение смещения (поиск HashTable) – это линейная операция наихудшего случая (O (n)), а предопределенные поиски свойств – сложные операции с постоянным временем (O (1)). С другой стороны, динамические свойства требуют другого поиска HashTable, линейной операции наихудшего случая (O (n)). Это означает, что доступ к динамическому свойству занимает в среднем примерно вдвое больше. Авторы Википедии могут объяснить Time-Complexity гораздо лучше, чем я могу.

Сначала модификаторы доступа могут показаться неактуальными. По мере того как вы идете вперед, вы скоро обнаружите, что иногда, вы просто не хотите, чтобы вероятность того, что какое-то свойство какого-либо объекта будет изменено некоторым кодом. Именно тогда вы видите ценность private .
Если объект содержит другой объект, который содержит всевозможные параметры, на которые будет опираться ваш код, например, вы, вероятно, будете использовать метод getter для доступа к этим настройкам извне, но вы оставите это фактическое свойство хорошо спрятанным используя private .

Если в дальнейшем по линии вы добавите модели данных и уровень обслуживания в свой проект, есть хорошие изменения, вы напишете (абстрактный) родительский класс, если только для типа-намекания.
Если эти экземпляры службы содержат что-то вроде свойства config, вы, вероятно, определите этот getter в родительском классе (чтобы определить его только один раз). private означает, что только текущий класс имеет доступ к свойству, но поскольку у вас не будет экземпляра родителя для работы, но экземпляр дочернего элемента, вы увидите, почему protected неоценима при работе с более крупными проектов.

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

 public function foo() { $temp = $this->getSomeValue(); return $temp ? $temp +1 : null; } 

Совершенно верно и не будет работать лучше, если вы должны написать

 public function foo() { $temp;// or $temp = null; $temp = $this->getSomeValue(); return $temp ? $temp +1 : null; } 

Однако, это не редкость, чтобы увидеть что-то вроде этого:

 public function bar($length = 1) { for ($i=0;$i<$length;$i++) { $return[] = rand($i+1, $length*10); } return $return; } 

Этот код основан на том, что PHP достаточно любезен для создания массива и присваивает ему $return когда $return[] = rand(); утверждение достигнуто. PHP сделает это, но установив ваш ini в E_STRICT | E_ALL E_STRICT | E_ALL покажет, что он не делает этого, не жалуясь на это. При передаче 0 методу массив не будет создан, и PHP также будет жаловаться, когда он достигнет return $return; statement: необъявленная переменная . Мало того, что это грязно, это также замедляет вас! Вам лучше объявить $return как массив в верхней части области:

 public function bar($length = 1) { $return = array();//that's it for ($i=0;$i<$length;$i++) { $return[] = rand($i+1, $length*10); } return $return; } 

Чтобы быть в безопасности, я также проверил бы тип аргумента:

 /** * construct an array with random values * @param int $length = 1 * @return array **/ public function bar($length = 1) { $length = (int) ((int) $length > 0 ? $length : 1);//make length > 0 $return = array(); for ($i=0;$i<$length;$i++) { $return[] = rand($i+1, $length*10); } return $return; } 

В большинстве случаев, если не во всех случаях: да .

Если переменные являются свойствами класса, они абсолютно должны быть объявлены перед использованием.

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

Если вы используете его в контексте всего класса, то да , вы должны определить свою переменную как член класса.

Однако, если вы говорите о локальной переменной в контексте одной функции, и переменная не должна использоваться нигде (или не возвращается), тогда нет.

По существу вам необходимо определить важность и объем вашей переменной, прежде чем принимать решение о том, сделать это свойством класса или нет.

Например:

 <?php class Test { private $test; // Private property, for use in the class only public $public_test; // Public Property, for use both internally and external to the class as a whole public function testing() { $local = 5; // Local variable, not needed outside of this function ever $this->test = rand(1, 5); $calc = $local * $this->test; // Local variable, not needed outside of this function ever $this->public_test = $calc / 2; // The only thing that the whole class, or public use cares about, is the result of the calculation divided by 2 } }