2010-09-23 4 views
5

Я использую Scanner class для чтения нескольких похожих файлов. Я хотел бы расширить его, чтобы убедиться, что все они используют один и тот же разделитель , и я также могу добавить методы, подобные skipUntilYouFind (String thisHere), что все они действительны для всех.Почему класс java.util.Scanner объявлен «final»?

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

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

+0

Если это связано с производительностью, теоретически возможно ли сделать сканер с неработоспособностью, который расширяется? Моя логика говорит, что это должно быть? – Roalt

ответ

4

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

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

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

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

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

+0

Это объясняет, почему функция nextBoolean должна быть определена как «final public boolean nextBoolean()», а не весь класс? – Roalt

+0

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

+1

По этой логике все должно быть окончательным классом. Я не могу честно полагать, что это причина. – corsiKa

0

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

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

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

+0

Создание композиции приведет к увеличению размера моего кода. Это не грех, но вы получите my.scanner.next() (или даже my.getScanner(). Next() вместо my.next(). Я думаю, что это не так красиво, верно? И это меньше "заменить это "by" that "... – Roalt

+0

Ну, если у вас есть для вашего объектаObject.scanner.next(), то это не инкапсуляция правильно? Но если у вас есть вашObject.process (input): returnVal, тогда вы это сделаете. –

1

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

Смежные вопросы