Які є вагомі причини заборонити спадкування на Java, наприклад, використовуючи остаточні класи або класи, використовуючи єдиний приватний конструктор без параметрів? Які вагомі причини зробити метод остаточним?
Які є вагомі причини заборонити спадкування на Java, наприклад, використовуючи остаточні класи або класи, використовуючи єдиний приватний конструктор без параметрів? Які вагомі причини зробити метод остаточним?
Відповіді:
Ваша найкраща посилання тут - пункт 19 чудової книги Джошуа Блоха "Ефективна Java", який називається "Дизайн та документ для отримання спадщини або забороняйте його". (Це пункт 17 у другому виданні та пункт 15 у першому виданні.) Ви справді повинні прочитати його, але я підсумую.
Взаємодія успадкованих класів з їхніми батьками може бути дивовижною і непередбачуваною, якщо предка не було призначено для спадкування.
Тому класи повинні бути двох видів:
Класи, розраховані на розширення , та з достатньою документацією, щоб описати, як це слід робити
Заняття відзначені фінальними
Якщо ви пишете суто внутрішній код, це може бути непосильним. Однак додаткових зусиль, пов’язаних із додаванням п’яти символів до файлу класу, дуже мало. Якщо ви пишете лише для внутрішнього споживання, то майбутній кодер завжди може видалити «остаточний» - ви можете вважати це застереженням: «цей клас не був розроблений з урахуванням спадкування».
Ви можете зробити метод остаточним, щоб переважаючі класи не могли змінити поведінку, на яку розраховано в інших методах. Методи, що називаються в конструкторах, часто оголошуються остаточними, тому при створенні об'єктів не виникає неприємних сюрпризів.
final
.
Однією з причин зробити остаточний клас було б, якщо ви хочете примусити склад над спадщиною. Це, як правило, бажано, щоб уникнути щільної зв'язку між класами.
Є 3 випадки використання, коли можна перейти до остаточних методів.
Призначення для завершення класу:
Так що жоден орган не може розширити ці заняття та змінити свою поведінку.
Напр .: Клас Wrapper Integer - це заключний клас. Якщо цей клас не є остаточним, то будь-який може поширити Integer на свій клас та змінити основну поведінку цілого класу. Щоб уникнути цього, java зробила всі класи обгортки як заключні класи.
DerivedInteger
, він досі не змінює початковий клас Integer, і той, хто використовує DerivedInteger
це робить на свій страх і ризик, тому я досі не розумію, чому це проблема.
ви можете створити незмінні об’єкти ( http://en.wikipedia.org/wiki/Immutable_object ), ви можете створити одиночний ( http://en.wikipedia.org/wiki/Singleton_pattern ) або ви хочете щоб не допустити, щоб хтось переосмислив метод з міркувань ефективності, безпеки або безпеки.
Спадщина - це як бензопила - дуже потужна, але жахлива в чужих руках. Або ви розробляєте клас, який має бути успадкований (що може обмежити гнучкість і зайняти набагато більше часу), або вам слід заборонити його.
Див. Ефективні пункти 16 та 17 другого видання Java або моє повідомлення в блозі "Податок на спадщину" .
Хммм ... я можу придумати дві речі:
У вас може бути клас, який займається певними проблемами безпеки. Підкласифікувавши його та подаючи вашій системі його підкласифіковану версію, зловмисник може обійти обмеження безпеки. Наприклад, ваша програма може підтримувати плагіни, і якщо плагін може просто підкласифікувати ваші відповідні класи для безпеки, він може використовувати цей трюк, щоб якось переправити підкласифіковану версію на місце. Однак це скоріше щось, з чим доводиться мати справу з аплетами тощо, можливо, не такий реалістичний випадок.
Набагато реалістичнішим є те, щоб уникнути того, як об'єкт стає незмінним. Наприклад, оскільки струни незмінні, ваш код може безпечно зберігати посилання на неї
String blah = someOtherString;
замість того, щоб скопіювати рядок спочатку. Однак, якщо ви можете підкласинг String, ви можете додати до нього методи, що дозволяють змінювати значення рядка, тепер жоден код не може покладатися на те, що рядок залишиться такою ж, якщо вона просто копіює рядок, як вище, замість цього вона повинна дублювати рядок.
Якщо ви позначаєте класи та методи як остаточні, ви можете помітити невеликий приріст продуктивності, оскільки під час виконання не потрібно шукати правильний метод класу, щоб викликати даний об’єкт. Незавершальні методи позначаються як віртуальні, щоб їх можна було належним чином розширити, а остаточні методи можна безпосередньо зв’язати або скласти вбудовано в класі.
Не дозволяти людям робити те, що може заплутати себе та інших. Уявіть бібліотеку фізики, де у вас є певні константи або обчислення. Не використовуючи остаточне ключове слово, хтось може зійти і переосмислити основні обчислення або константи, які НІКОЛИ не повинні змінюватись.
Ви хочете зробити метод остаточним, щоб переважаючі класи не змінювали його поведінку. Коли ви хочете мати можливість змінити поведінку, зробіть метод загальнодоступним. Коли ви перекриєте публічний метод, його можна змінити.