Коли ми створюємо клас, який успадковується від абстрактного класу, і коли ми реалізуємо успадкований абстрактний клас, чому ми повинні використовувати ключове слово override?
"Чому?" на такі питання важко відповісти, оскільки вони розпливчасті. Я припускаю, що ваше питання полягає в тому, "які аргументи можна зробити під час мовної розробки, щоб аргументувати позицію про те override, що потрібне ключове слово ?"
Почнемо з кроку назад. У деяких мовах, скажімо, Java, методи за замовчуванням є віртуальними і автоматично змінюються. Дизайнери C # знали про це і вважали це незначним недоліком у Java. Як говорили деякі, C # не є "Java з виведеними тупими частинами", але дизайнери C # прагнули дізнатися з проблемних пунктів дизайну C, C ++ та Java, а не тиражувати їх у C #.
Дизайнери C # розглядали можливе джерело помилок; зрештою, це спосіб змінити поведінку існуючого, перевіреного коду , і це небезпечно. Переосмислення - це не те, що слід робити випадково або випадково; це повинно бути розроблено тим, хто над цим важко думає . Ось чому методи за замовчуванням не є віртуальними, і чому вам потрібно сказати, що ви переосмислюєте метод.
Ось основні міркування. Тепер ми можемо розібратися в більш досконалих міркуваннях.
Відповідь StriplingWarrior дає хороший перший крок у висуванні більш просунутого аргументу. Автор похідного класу може бути неінформований про базовий клас, може мати намір здійснити новий метод, і ми не повинні допускати, щоб користувач помилково переосмислював .
Хоча цей пункт є розумним, існує ряд контраргументів, таких як:
- Автор похідного класу несе відповідальність знати все про базовий клас! Вони повторно використовують цей код, і вони повинні зробити належну ретельність, щоб досконало зрозуміти цей код перед повторним його використанням.
- У вашому конкретному сценарії віртуальний метод абстрактний; було б помилкою не перекрити її, і тому навряд чи автор створив би реалізацію випадково.
Давайте тоді зробимо ще більш просунутий аргумент з цього приводу. За яких обставин можна виправдати автора похідного класу за те, що він не знає, що робить базовий клас? Ну, врахуйте цей сценарій:
- Автор базового класу складає абстрактний базовий клас B.
- Автор похідного класу в іншій команді робить похідний клас D методом М.
- Автор базового класу розуміє, що командам, які розширюють базовий клас B, завжди потрібно буде запропонувати метод M, тому автор базового класу додає абстрактний метод М.
- Коли клас D перекомпілюється, що відбувається?
Що ми хочемо, щоб автор D повідомив, що щось відповідне змінилося . Відповідне, що змінилося, - це те, що М тепер є вимогою і що їх реалізація повинна бути перевантажена. DM може знадобитися змінити свою поведінку, як тільки ми дізнаємось, що його можна викликати з базового класу. Правильна річ - це не мовчки говорити "о, DM існує і розширює BM". Правильна річ, яку повинен зробити компілятор, - це невдача , і скажіть: "Ей, авторе D, перевіри це твоє припущення, яке більше не дійсне, і за необхідності виправити свій код".
У вашому прикладі, припустимо , що overrideбуло необов'язково на , SayHelloтому що це перевизначення абстрактний метод. Існує дві можливості: (1) автор коду має намір замінити абстрактний метод, або (2) метод переосмислення відміняється випадково, тому що хтось інший змінив базовий клас, і код зараз помилився дещо тонко. Ми не можемо розрізнити ці можливості, якщо overrideце необов'язково .
Але якщо overrideце потрібно, то ми можемо розрізнити три сценарії. Якщо в коді можлива помилка, то overrideвона відсутня . Якщо це навмисно переосмислюється, тоді overrideвоно присутнє . І якщо він навмисно НЕ перекриваючи то newє присутній . Дизайн C # дозволяє нам зробити ці тонкі відмінності.
Пам'ятайте, що повідомлення про помилки компілятора вимагає читання розуму розробника ; компілятор повинен вивести з неправильного коду, який правильний код, мабуть, мав на увазі автор , і надати помилку, яка спрямовує їх у правильному напрямку. Чим більше підказок ми можемо змусити розробника залишити в коді про те, про що вони думали, тим краще робота компілятора у виконанні повідомлень про помилки, а отже, тим швидше ви зможете знайти та виправити ваші помилки.
Але загалом, C # був розроблений для світу, в якому змінюється код . Дуже багато функцій C #, які здаються "непарними", насправді є, оскільки вони повідомляють розробника, коли припущення, яке раніше було дійсним , стає недійсним, оскільки змінився базовий клас. Цей клас помилок називають "крихкими збитками базового класу", а C # має ряд цікавих заходів щодо зменшення цього класу.