На мой взгляд, хорошей практикой является создание простых типов значений final
. Если вы хотите гарантировать неизменность, вам фактически нужно сделать это. Это также (частично), почему String
, Integer
и т. д. все final
.
Если ваш класс не final
, кто-нибудь может расширить его, добавив методы, которые его видоизменяют. Клиент, которому передается экземпляр расширенного типа (преобразованный в ваш тип), ошибочно полагает, что имеет дело с неизменяемым объектом, хотя на самом деле это не так.
В моем собственном коде я пошел немного дальше и сделал почти любой класс final
, если я не проектировал его с явным учетом расширяемости. Если вы хотите поддерживать расширение, рассмотрите возможность предоставления абстрактного класса или интерфейса. Это также соответствует аннотации, final или пустое правило для методов.
Обновление. Почему для неизменности требуется, чтобы класс был final
? Конечно, есть и другие способы гарантировать неизменность определенного атрибута объекта.
Рассмотрим, например, класс RGBColor
с тремя атрибутами red
, green
и blue
типа byte
. Делаем все три final
и устанавливаем их в конструкторе раз и навсегда. (Мы можем дополнительно сделать их private
и добавить соответствующие методы получения, но это не важно для данного обсуждения.) Конечно, мы переопределяем метод equals
, чтобы он возвращал true
тогда и только тогда, когда сравниваемый объект является экземпляром RGBColor
с тем же самым red
, green
и blue
значения.
Это выглядит невинно, но что, если кто-то решит расширить наш класс до класса RGBAColor
, добавив атрибут alpha
? Естественно, расширитель захочет переопределить equals
, чтобы также принять во внимание значение alpha
. Предположим, что наш расширитель также не очень заботится о неизменяемости и, таким образом, делает alpha
не-final
и предоставляет для него сеттер.
Теперь, если нам дан объект типа RGBColor
, мы не можем с уверенностью предположить, что, если он сравнивается с другим, он все еще будет делать это через минуту. Мы могли бы предотвратить эту (конкретную проблему), также объявив equals
как final
в нашем классе RGBColor
. Но тогда мы могли бы с таким же успехом сделать весь класс final
, потому что расширение типа значения без возможности расширения понятия равенства практически бесполезно. (Есть и другие проблемы с переопределением equals
, такие как несимметричность. Обычно мне это не очень удобно.)
person
5gon12eder
schedule
15.09.2014