Почему класс java.util.Scanner объявлен как финальный? - PullRequest
5 голосов
/ 23 сентября 2010

Я использую Класс сканера для чтения нескольких похожих файлов. Я хотел бы расширить его, чтобы убедиться, что все они используют один и тот же разделитель , и я также могу добавить такие методы, как skipUntilYouFind (String thisHere) , которые действительны для всех них.

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

Я нашел некоторые причины для объявления класса final, но почему это здесь делается?

Ответы [ 3 ]

4 голосов
/ 23 сентября 2010

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

Например, рассмотрим следующий метод в классе:

public boolean nextBoolean()  {
    clearCaches();
    return Boolean.parseBoolean(next(boolPattern()));
}

Скажем, вы хотите перезаписать это, потому что вы хотите, чтобы 'awesome' оценивался как 'true' boolean (по любой причине). Если вы перезаписаете его, вы не сможете вызвать super.nextBoolean (), поскольку он будет использовать следующий токен с использованием логики по умолчанию. Но если вы не вызовете super.nextBoolean (), clearCaches () не будет вызываться, возможно, нарушая другие не перезаписанные методы. Вы не можете вызывать clearCaches (), потому что это личное. Если бы они сделали это защищенным, но потом поняли, что это вызывает проблемы с производительностью, и хотели новую реализацию, которая больше не очищает кеши, то они могут сломать вашу перезаписанную реализацию, которая все равно будет вызывать это.

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

1 голос
/ 23 сентября 2010

Полагаю, это связано с соображениями безопасности.Этот класс читает пользовательский ввод, так что кто-то с плохими намерениями может расширить его, изменить его поведение, и вы будете облажаны.Если он окончательный, для плохого парня это не так просто, потому что если он сделает свой собственный тип сканера (не java.util.Scanner), принципы полиморфизма будут нарушены.Видите, плохой парень может быть достаточно умен, чтобы написать бота / скрипт, который делает это автоматически на удаленных серверах ... Он может даже сделать это путем динамической загрузки классов в скомпилированном приложении.

0 голосов
/ 23 сентября 2010

Я думаю, что ссылка, которую вы предоставили, объясняет все это.

В вашем случае кажется, что вы все равно должны предпочесть композицию вместо наследования.Вы создаете утилиту с предопределенным поведением, которая может скрывать некоторые (или все) детали класса Scanner.

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

...