Intereting Posts
Скопировать изображение с удаленного сервера через HTTPS jquery / ajax form – serverside php, но получить предупреждение о перекрестном домене Ретрансляция недопустимого сообщения при отправке почты с помощью функции PHP как я могу заставить мой локоть ждать несколько секунд до соскабливания? PHP Multi Byte str_replace? Статический метод get – это плохая практика? переменные, передающие ничего, показывают неопределенную ошибку переменной, поэтому вы хотите поместить значение по умолчанию для переменной Как изменить symfony 2 doctrine mapper для использования моего настраиваемого каталога вместо моего Entity Directory в комплекте Как передать json-данные в html с php? Имитировать файловую структуру с PHP Использование JavaScript для отображения переменной Laravel Как использовать array_count_values ​​() и mySQL для подсчета значения PHP-скрипт для поиска имени веб-сервера Facebook CurlException: 6: Не удалось разрешить хост 'graph.facebook.com' Как установить драйвер mysqlnd с помощью MAMP?

Неужели это неправильно, если не использовать сеттеров и геттеров?

Я немного новый в PHP. По какой-то причине в других типах языков программирования, таких как JAVA, у меня нет проблем с использованием сеттеров и геттеров для каждой отдельной переменной, но когда я программирую на PHP, вероятно, потому, что он настолько гибкий, он чувствует себя как пустая трата времени. Намного проще просто устанавливать атрибуты класса как публичные большую часть времени и манипулировать ими таким образом. Дело в том, что, когда я это делаю, я чувствую, что делаю что-то неправильно и иду против принципов OO.

Неужели это неправильно, если не использовать сеттеров и геттеров? Почему или почему нет? Как вы, ребята, делаете это большую часть времени?

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

Для частного кода или небольших приложений вполне возможно просто закрыть его. IDE (или текстовый редактор) позволит вам сгенерировать шаблон доступа и скрыть его с помощью сворачивания кода. Это, по-видимому, упрощает использование геттеров и сеттеров.

Обратите внимание, что некоторые языки программирования имеют функции для синтеза поля по умолчанию + getter + setter – Ruby делает это с помощью метапрограммирования, C # имеет автоматически реализованные свойства. И Python полностью обходит эту проблему, позволяя вам переопределить доступ к атрибутам, позволяя вам инкапсулировать атрибут в подклассе, который ему нужен, вместо того, чтобы беспокоиться об этом. (Это тот подход, который мне больше всего нравится.)

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

Если мы говорим строго о PHP здесь, а не о C #, Java и т. Д. (Где компилятор будет оптимизировать эти вещи), я считаю, что геттеры и сеттеры являются пустой тратой ресурсов, где вам просто нужно проксировать значение частного поля и ничего не делать.

В моей настройке я сделал два дерьмовых класса, один из которых состоял из пяти частных полей, инкапсулированных пятью парами getter / setter, проксимирующих поле (которое выглядело почти точно как java-код, достаточно забавно), а другое с пятью общедоступными полями и называлось memory_get_usage () в конец после создания экземпляра. В сценарии с геттерами / сеттерами использовано 59708 байт памяти, а скрипт с общедоступными полями – 49244 байт.

В контексте библиотеки классов любого значительного размера, такого как структура веб-сайта, эти бесполезные геттеры и сеттеры могут добавить к ОГРОМНОЙ черной дыре для памяти. Я разрабатываю рамки для своего работодателя на PHP (их выбор, а не мой. Я бы не использовал его для этого, если бы у меня был выбор, но, сказав это, PHP не налагает никаких непреодолимых ограничений на нас), и когда я реорганизую библиотека классов для использования публичных полей вместо геттеров / сеттеров, весь shebang в конечном итоге использовал на 25% меньше памяти на запрос по крайней мере.

Методы __get (), __set () и __call () «magic» действительно светят для обработки изменений интерфейса. Когда вам нужно перенести поле в getter / setter (или getter / setter в поле), они могут сделать процесс прозрачным для любого зависимого кода. С интерпретируемым языком немного сложнее найти все способы использования поля или метода даже при достаточно хорошей поддержке чувствительности кода, предоставляемой Eclipse PDT или Netbeans, поэтому магические методы полезны для обеспечения того, чтобы старый интерфейс все еще делегировал новый функциональность.

Скажем, у нас есть объект, который был разработан с использованием полей вместо геттеров / сеттеров, и мы хотим переименовать поле «поле» в «fieldWithBetterName», потому что «поле» было неуместным или больше не описывало использование точно или просто просто неправильно. И скажем, мы хотели изменить поле под названием «field2», чтобы ленить загружать его значение из базы данных, потому что изначально неизвестно, используя геттер …

 class Test extends Object { public $field; public $field2; } 

становится

 class Test extends Object { public $fieldWithBetterName = "LA DI DA"; private $_field2; public function getField2() { if ($this->_field2 == null) { $this->_field2 = CrapDbLayer::getSomething($this->fieldWithBetterName); } return $this->_field2; } public function __get($name) { if ($name == 'field')) { Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace()); return $this->fieldWithBetterName; } elseif ($name == 'field2') { Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace()); return $this->getField2(); } else return parent::__get($name); } } $t = new Test; echo $t->field; echo $t->field2; 

(Как примечание, бит «extends Object» – это только базовый класс, который я использую практически для всего, у которого есть объявление __get () и __set (), которое генерирует исключение, когда к незанятым полям обращаются)

Вы можете вернуться назад с помощью __call (). Этот пример довольно хрупкий, но его нетрудно очистить:

 class Test extends Object { public $field2; public function __call($name, $args) { if (strpos($name, 'get')===0) { $field = lcfirst($name); // cheating, i know. php 5.3 or greater. not hard to do without it though. return $this->$field; } parent::__call($name, $args); } } 

Методы Getter и setter в PHP хороши, если сеттер должен что-то делать, или если у получателя есть ленивая загрузка чего-либо или что-то было создано или что-то еще, но они не нужны и расточительны, если они не делают ничего, кроме прокси-сервера в области, особенно с помощью нескольких методов, подобных описанным выше, для управления изменениями интерфейса.

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

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

Вы считали, что используете магические функции __set / __ get? Используя их, вы можете легко объединить все функции getter / setter только в 2 функциях!

Существует способ эмулировать get / set без фактического использования класса функций get / set, поэтому ваш код остается аккуратным:

 $person->name = 'bob'; echo $person->name; 

Взгляните на этот класс, который я закодировал.

Как правило, при использовании этого класса вы объявляете все свои свойства защищенными (или частными). В случае, если вы хотите добавить поведение свойства, скажите strtolower () + ucfirst () в свойстве «name», все, что вам нужно сделать, это объявить защищенную функцию set_name () в вашем классе и поведение должно автоматически подбираться. То же самое можно сделать с помощью get_name ().

 // Somewhere in your class (that extends my class). protected function set_name($value) { $this->name = ucfirst(strtolower($value)); } // // Now it would store ucfirst(strtolower('bob')) automatically. $person->name = 'bob'; 

PS Еще одна интересная вещь: вы можете создавать несуществующие поля, такие как

 echo $person->full_name; 

без наличия таких полей (пока существует функция get_full_name ()).

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

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