Я занимаюсь рефакторингом старого сайта PHP OOP.
Мне так хочется начать использовать 'final' на классах для " make it explicit that the class is currently not extended by anything
". Это может сэкономить много времени, если я приду в класс, и мне интересно, могу ли я переименовать / удалить / изменить protected
свойство или метод. Если я действительно хочу расширить класс, я могу просто удалить ключевое слово final, чтобы разблокировать его для расширения.
Т.е. если я прихожу в класс, в котором нет дочерних классов, я могу записать эти знания, отметив класс как окончательный. В следующий раз, когда я приду к нему, мне не придется повторно искать кодовую базу, чтобы увидеть, есть ли у нее дети. Это экономит время при рефакторинге.
Все это кажется разумной идеей, позволяющей сэкономить время ... но я часто читал, что занятия должны быть окончательными только в редких / особых случаях.
Может быть, это портит создание объекта Mock или имеет другие побочные эффекты, о которых я не думаю.
Чего мне не хватает?
источник
Ответы:
Тот, кто написал это неправильно. Используйте
final
свободно, в этом нет ничего плохого. Он документирует, что класс не был спроектирован с учетом наследования, и это обычно верно для всех классов по умолчанию: разработка класса, от которого может быть унаследовано значительное значение, занимает больше, чем просто удалениеfinal
спецификатора; это требует большой заботы.Таким образом, использование
final
по умолчанию ни в коем случае не плохо. На самом деле, многие люди предполагают, что это должно быть по умолчанию, например, Джон Скит .Это действительно предупреждение, но вы всегда можете прибегнуть к интерфейсам, если вам нужно высмеивать ваши классы. Это, безусловно, лучше, чем сделать все классы открытыми для наследования только с целью насмешки.
источник
final
играл бы гораздо большую роль.Если вы хотите оставить себе примечание о том, что у класса нет подклассов, то обязательно сделайте это и используйте комментарий, вот для чего они. Ключевое слово «final» - это не комментарий, а использование языковых ключевых слов просто для того, чтобы что-то сигнализировать вам (и только вы когда-либо знаете, что это значит) - плохая идея.
источник
final
как ожидалось. В этом нет ничего плохого. А использование языковой функции для принудительного применения ограничения всегда лучше, чем использование комментария.final
должно означать «Никакой подкласс этого класса не должен создаваться» (по юридическим причинам или что-то в этом роде), а не «у этого класса в настоящее время нет детей, поэтому я все еще в безопасности связываться с его защищенными членами». Цельfinal
- полная противоположность «свободно редактируемому», и уfinal
класса даже не должно бытьprotected
членов!final
означает «этот класс не должен быть расширен [пока]». Ни больше, ни меньше. Было ли PHP разработано с учетом этой философии, не имеет значения: в конце концов, в нем естьfinal
ключевое слово. Во-вторых, спор о дизайне PHP обречен на провал, учитывая то, как PHP-дизайн сложен и в целом плох.Есть хорошая статья о том, «Когда объявлять классы окончательными» . Несколько цитат из этого:
PS Спасибо @ocramius за отличное чтение!
источник
«окончательный» для класса означает: вы хотите подкласс? Давай, удаляй «финал», подкласс сколько хочешь, но не жалуйся мне, если он не работает. Ты сам по себе.
Когда класс может быть разделен на подклассы, это поведение, на которое полагаются другие, должно быть описано в абстрактных терминах, которым подчиняются подклассы. Вызывающие должны быть написаны, чтобы ожидать некоторую изменчивость. Документация должна быть написана тщательно; Вы не можете сказать людям «посмотрите на исходный код», потому что исходный код еще не там. Это все усилия. Если я не ожидаю, что класс находится в подклассе, это ненужное усилие. «final» ясно говорит, что эти усилия не были предприняты, и дает справедливое предупреждение.
источник
Одна вещь, о которой вы, возможно, и не задумывались, это тот факт, что ЛЮБОЕ изменение класса означает, что он должен пройти новое QA-тестирование.
Не отмечайте вещи как окончательные, если вы действительно, действительно не имеете это в виду.
источник
final
(изменение), тогда я просто должен повторно протестировать его?final
. Это опыт из первых рук?final
класса есть один основной вариант использования. У вас есть полиморфные классы, которые вы не хотите расширять, потому что подкласс может нарушить полиморфизм. Не используйте,final
если вы не должны предотвращать создание подклассов. Кроме этого, это бесполезно.Использование 'final' лишает свободы других, которые хотят использовать ваш код.
Если код, который вы пишете, предназначен только для вас и никогда не будет выпущен для широкой публики или для клиента, то вы, конечно, можете делать со своим кодом то, что вы хотите. В противном случае вы не позволите другим использовать ваш код. Слишком часто мне приходилось работать с API, который было бы легко расширять для моих нужд, но потом мне мешал «финал».
Кроме того, часто есть код, который лучше не делать
private
, ноprotected
. Конечно,private
означает «инкапсуляция» и скрывает вещи, которые считаются деталями реализации. Но, как программист API, я мог бы также задокументировать тот факт, что методxyz
считается деталью реализации и, таким образом, может быть изменен / удален в будущей версии. Поэтому каждый, кто будет полагаться на такой код, несмотря на предупреждение, делает это на свой страх и риск. Но он действительно может сделать это и повторно использовать (надеюсь, уже протестированный) код и быстрее найти решение.Конечно, если реализация API с открытым исходным кодом, можно просто удалить «финал» или сделать методы «защищенными», но затем вы изменили код и должны отслеживать изменения в форме патчей.
Однако, если реализация с закрытым исходным кодом, вы остаетесь с поиском обходного пути или, в худшем случае, с переключением на другой API с меньшими ограничениями в отношении возможностей для настройки / расширения.
Обратите внимание, что я не считаю, что 'final' или 'private' - это зло, но я думаю, что они используются слишком часто, потому что программист не думал о своем коде с точки зрения повторного использования и расширения кода.
источник