Пун намеревался… Давайте обсудим final
Java.
Недавно наш популярный пост в блоге «10 тонких передовых методов при кодировании Java» значительно обновился и получил новый набор комментариев, поскольку он был обобщен и связан с JavaWorld . В частности, редакторы JavaWorld оспорили наше мнение о ключевом слове Java « final
»:
Более спорно, Эдер берет на себя вопрос о ли это когда-нибудь безопасно сделать методы конечных по умолчанию:
«Если вы полностью контролируете весь исходный код, нет ничего плохого в том, чтобы сделать методы финальными по умолчанию, потому что:»
- «Если вам нужно переопределить метод (правда?), Вы все равно можете удалить ключевое слово final»
- «Вы никогда не будете случайно отменять любой метод»
Да, в самом деле. Все классы, методы, поля и локальные переменные должны быть окончательными по умолчанию и изменяемыми через ключевое слово.
Вот поля и локальные переменные:
1
2
3
|
int finalInt = 1 ; val int finalInt = 2 ; var int mutableInt = 3 ; |
Вопрос о том, действительно ли ключевое слово val
стиле Scala / C # действительно необходимо, является дискуссионным. Но ясно, чтобы снова модифицировать поле / переменную, у нас должно быть ключевое слово, явно позволяющее это сделать. То же самое для методов — и я использую ключевое слово по default
Java 8 для улучшения согласованности и регулярности:
1
2
3
4
5
6
7
8
|
class FinalClass { void finalMethod() {} } default class ExtendableClass { void finalMethod () {} default void overridableMethod() {} } |
По нашему мнению, это был бы идеальный мир, но Java идет другим путем, делая default
(переопределяемый, изменяемый) по умолчанию и final
(не переопределяемый, неизменяемый) явным вариантом.
Справедливо, мы будем жить с этим
… И как разработчики API ( конечно , из jOOQ API), мы просто с радостью поместим final
повсюду, чтобы хотя бы притвориться, что Java имеет более разумные значения по умолчанию, упомянутые выше.
Но многие люди не согласны с этой оценкой, в основном по той же причине:
Как человек, который работает в основном в среде OSGI, я не могу не согласиться, но можете ли вы гарантировать, что другой дизайнер API чувствовал то же самое? Я думаю, что лучше предупреждать ошибки разработчиков API, чем предупреждать ошибки пользователей, устанавливая ограничения на то, что они могут расширять по умолчанию. — eliasv на Reddit
Или же…
Сильно не согласен. Я бы предпочел запретить окончательный и частный доступ к публичным библиотекам. Такая боль, когда мне действительно нужно что-то расширить, а это невозможно.
Преднамеренная блокировка кода может означать две вещи: либо отстой, либо безупречна. Но если он идеален, то никому не нужно его расширять, так почему вас это волнует?
Конечно, существуют веские причины использовать final, но боязнь взломать кого-либо новой версией библиотеки не является одной из них. — meotau на reddit
Или также …
Я знаю, что у нас уже был очень полезный разговор об этом, но только для того, чтобы напомнить другим людям в этой теме: большая часть дебатов вокруг «финала» зависит от контекста: это публичный API или это внутренний код? В первом контексте я согласен, что есть несколько хороших аргументов для финала. В последнем случае final почти всегда является ПЛОХОЙ идеей. — Чарльз Рот в нашем блоге
Все эти аргументы имеют тенденцию идти в одном направлении: «Мы работаем над дрянным кодом, поэтому нам нужен хотя бы какой-то обходной путь, чтобы облегчить боль».
Но почему бы не подумать об этом так:
Разработчики API, которые имеют в виду все вышеперечисленные люди, создадут именно тот ужасный API, который вы хотели бы патчить через расширение. По совпадению, тот же самый дизайнер API не будет размышлять о полезности и коммуникативности ключевого слова final
и, следовательно, никогда не будет использовать его, если этого не требует язык Java. Беспроигрышный вариант (хотя и дрянной API, шаткие обходные пути и патчи).
Разработчики API, которые хотят использовать final для своих API, будут много размышлять о том, как правильно проектировать API (и четко определенные точки расширения / SPI), так что вы никогда не будете беспокоиться о том, что что-то будет final
. Опять же, беспроигрышный (и потрясающий API).
Плюс, в последнем случае, странный хакер будет защищен от взлома и взлома вашего API таким образом, что это приведет только к боли и страданиям, но это на самом деле не потеря.
Окончательные методы интерфейса
По вышеупомянутым причинам я все еще глубоко сожалею о том, что final
невозможен в интерфейсах Java 8. Брайан Гетц дал превосходное объяснение, почему так принято. На самом деле обычное объяснение. Тот, который не является главной целью дизайна для изменений!
Но подумайте о последовательности, регулярности языка, если бы мы имели:
1
2
3
4
5
|
default interface ImplementableInterface { void abstractMethod () ; void finalMethod () {} default void overridableMethod() {} } |
(Утки и бега…)
Или, более реалистично, с нашим статус-кво по default
по default
:
1
2
3
4
5
|
interface ImplementableInterface { void abstractMethod () ; final void finalMethod () {} void overridableMethod() {} } |
в заключение
Итак, еще раз, каковы ваши (последние) мысли по этому обсуждению?
Если вы не слышали достаточно, подумайте также о том, чтобы прочитать этот замечательный пост доктора Дэвида Пирса , автора временного языка программирования .
Ссылка: | Это финальная дискуссия! от нашего партнера JCG Лукаса Эдера в блоге JAVA, SQL и JOOQ . |