Хорошие причины запретить наследование в Java?

java inheritance final

54653 просмотра

11 ответа

Каковы веские причины для запрета наследования в Java, например, с помощью конечных классов или классов, использующих один частный конструктор без параметров? Каковы веские причины сделать метод окончательным?

Автор: cretzel Источник Размещён: 11.11.2019 02:19

Ответы (11)


173 плюса

Решение

Ваша лучшая ссылка здесь - это пункт 19 из превосходной книги Джошуа Блоха «Эффективная Ява» под названием «Дизайн и документ для наследования, или же запретить его». (Это пункт 17 во втором издании и пункт 15 в первом издании.) Вы действительно должны прочитать его, но я подведу итоги.

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

Поэтому классы должны быть двух видов:

  1. Классы, предназначенные для расширения , и с достаточным количеством документации, чтобы описать, как это должно быть сделано

  2. Классы отмечены как финал

Если вы пишете чисто внутренний код, это может быть немного излишним. Однако дополнительные усилия по добавлению пяти символов в файл класса очень малы. Если вы пишете только для внутреннего потребления, будущий кодер всегда может удалить «финал» - вы можете думать об этом как о предупреждении «этот класс не был разработан с учетом наследования».

Автор: DJClayworth Размещён: 20.10.2008 03:10

22 плюса

Возможно, вы захотите сделать метод final, чтобы переопределенные классы не могли изменить поведение, на которое рассчитывают другие методы. Методы, вызываемые в конструкторах, часто объявляются как final, поэтому при создании объектов вы не получите неприятных сюрпризов.

Автор: Bill the Lizard Размещён: 20.10.2008 03:10

18 плюса

Одной из причин сделать класс финальным будет то, что вы хотите навязать композицию наследованию. Это обычно желательно во избежание тесной связи между классами.

Автор: John Topley Размещён: 20.10.2008 03:11

13 плюса

Есть 3 варианта использования, где вы можете пойти на финальные методы.

  1. Во избежание переопределения производного класса определенной функциональности базового класса.
  2. Это делается в целях безопасности, где базовый класс предоставляет некоторые важные базовые функциональные возможности платформы, где производный класс не должен ее изменять.
  3. Финальные методы работают быстрее, чем методы экземпляров, так как для финальных и закрытых методов не используется концепция виртуальной таблицы. Поэтому, когда есть возможность, попробуйте использовать финальные методы.

Цель сделать финал урока:

Так что никто не может расширить эти классы и изменить их поведение.

Например: класс Wrapper Integer является конечным классом. Если этот класс не является окончательным, то любой может расширить Integer в свой собственный класс и изменить базовое поведение целочисленного класса. Чтобы избежать этого, java сделал все классы-обёртки финальными.

Автор: user1923551 Размещён: 13.12.2013 04:28

12 плюса

вы можете создавать неизменяемые объекты ( http://en.wikipedia.org/wiki/Immutable_object ), создавать одиночный ( http://en.wikipedia.org/wiki/Singleton_pattern ) или создавать предотвращать переопределение метода по соображениям эффективности, безопасности или безопасности.

Автор: Ray Tayek Размещён: 20.10.2008 03:21

6 плюса

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

См. Пункты «Эффективная Java 2-е издание», пункты 16 и 17, или мой пост в блоге «Налог на наследство» .

Автор: Jon Skeet Размещён: 20.10.2008 03:12

4 плюса

Хммм ... я могу думать о двух вещах:

У вас может быть класс, который занимается определенными проблемами безопасности. Подклассифицируя его и передавая его системе подклассовую версию, злоумышленник может обойти ограничения безопасности. Например, ваше приложение может поддерживать плагины, и если плагин может просто подклассить ваши классы, относящиеся к безопасности, он может использовать этот трюк, чтобы каким-то образом перебросить его подклассовую версию на место. Однако Sun, скорее, имеет дело с апплетами и тому подобным, может быть, это не совсем реалистичный случай.

Гораздо более реалистичным является избегать изменения объекта. Например, поскольку строки неизменяемы, ваш код может безопасно хранить ссылки на него

 String blah = someOtherString;

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

Автор: Mecki Размещён: 20.10.2008 03:13

1 плюс

Чтобы люди не могли делать то, что могло бы сбить их с толку и окружающих. Представьте себе физическую библиотеку, в которой у вас есть определенные константы или расчеты. Без использования ключевого слова final кто-то может прийти и переопределить базовые вычисления или константы, которые никогда не должны изменяться.

Автор: Anson Smith Размещён: 20.10.2008 03:12

1 плюс

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

Автор: DavidG Размещён: 20.10.2008 03:51

1 плюс

Если вы пометите классы и методы как окончательные, вы можете заметить небольшой выигрыш в производительности, поскольку среда выполнения не должна искать правильный метод класса для вызова данного объекта. Не финальные методы помечаются как виртуальные, чтобы при необходимости их можно было расширять, а финальные методы можно напрямую связать или скомпилировать в классе внутри класса.

Автор: seanalltogether Размещён: 20.10.2008 05:35

0 плюса

Вы хотите сделать метод final, чтобы переопределение классов не изменило его поведение. Если вы хотите изменить поведение, сделайте метод общедоступным. Когда вы переопределяете публичный метод, его можно изменить.

Автор: Alexander Robinson Размещён: 10.11.2015 09:29
Вопросы из категории :
32x32