Это может быть основной вопрос, но это заставило меня задуматься довольно долгое время.
Должен ли я объявлять все частные / локальные переменные частным? Или это необходимо только для «важных» переменных?
Например, у меня есть (временный) результат вычисления. Должен ли я предварительно объявить эту переменную?
Надеюсь, кто-то может это указать.
Как правило, это правильное правило для определения переменных и их инициализации перед использованием. Это включает в себя не только определение и начальное значение, но также проверку и фильтрацию входных значений, так что все предварительные условия, на которых основан фрагмент кода, устанавливаются до конкретной обработки данных, содержащихся в этих переменных.
То же самое относится к объектам (свойствам), поскольку они являются переменными всего объекта. Поэтому они должны быть определены в классе уже (по умолчанию их значение 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 } }