Інтерпретація 1
У C# Abstract і Virtual є заплутаними, обидва пов'язані з успадковуванням і передбачають використання override. Давайте обговоримо відмінності між ними:
1. Віртуальний метод
Віртуальне ключове слово використовується для зміни методів у базовому класі. Існують дві ситуації, коли використовується віртуальний режим:
Сценарій 1: Віртуальний метод визначений у базовому класі, але віртуальний метод не переписується у похідному класі. У виклику екземпляра похідного класу віртуальний метод використовує метод, визначений базовим класом.
Сценарій 2: Віртуальний метод визначається у базовому класі, а потім метод переписується за допомогою перевизначення в похідному класі. У виклику екземпляра похідного класу віртуальний метод використовує похідний метод перезапису.
2. Абстрактний метод (абстрактний метод)
Абстрактне ключове слово можна використовувати лише в абстрактних класах для зміни методів, і спеціальної реалізації немає. Реалізація абстрактних методів має бути реалізована за допомогою ключового слова override у похідному класі.
Найважливіша різниця між інтерфейсом і абстрактним класом: абстрактний клас — це неповний клас, абстракція об'єкта, тоді як інтерфейс — це поведінкова норма.
3. Ключові слова
Статичний: Коли метод оголошується як статичний, метод є статичним, і компілятор зберігає реалізацію методу під час компіляції. Тобто метод належить класу, але не жодному члену, незалежно від існування екземпляра класу чи ні. Як і функція входу Static void Main, оскільки це статична функція, її можна викликати безпосередньо.
Virtua: Коли метод оголошений як Virtual, він залишається віртуальним, доки ви не використаєте змінну ClassName = нову ClassName(); Перед оголошенням екземпляра класу він не існує у реальному просторі пам'яті. Це ключове слово дуже часто використовується у спадкуванні класів для забезпечення підтримки поліморфізму для класових методів.
overrride: позначає переписування. Цей клас успадковує від класу Shape Віртуальний, абстрактний — це сказати іншим класам, які хочуть успадкувати від нього, що ти можеш перевизначити мій метод або властивість, інакше це не дозволено. Анотація: Оголошення абстрактного методу — це метод, який має бути замінений похідним класом, який використовується для спадкування; Його можна розглядати як уявний метод без реалізації; Якщо клас містить абстрактний метод, то цей клас має бути визначений як абстрактний клас, незалежно від того, чи містить він інші загальні методи; Абстрактні класи не можуть мати субстанції.
a) Метод віртуальної модифікації повинен мати реалізацію методу (навіть якщо це лише пара дужок), і метод абстрактної модифікації не може мати реалізацію.
b) virtual можна переписати підкласами, abstract потрібно переписати підкласами
c) Якщо функція в класі модифікована абстактом, ім'я класу також має бути змінене за допомогою абстакту
d) Абстрактні модифіковані класи не можуть бути створені екземплярами.
e) Якщо метод у C# готовий переписати батьківський клас у підкласі, метод має бути модифікований віртуальним у батьківському класі та overide у підкласі, щоб уникнути випадкового переписування батьківського методу батьківського класу в підкласі.
Примітка: класи, модифіковані абстрактними, можуть бути лише успадковані, а не інстанційовані.
Інтерпретація 2
Як віртуальний, так і абстрактний використовуються для зміни батьківського класу, що дозволяє перевизначити дочірній клас шляхом перевизначення батьківського класу.
У них є одна спільна риса: якщо їх використовують для зміни методів, публічні мають бути додані перед ними, інакше виникнуть помилки компіляції: віртуальні чи абстрактні методи не можуть бути приватними. Адже додавання віртуального або абстрактного дозволяє переосмислити підклас, а приватні члени не можуть бути доступні підкласом.
Але вони дуже різні. (віртуальне — це «віртуальне», абстрактне — «абстрактне»).
(1) Метод віртуальної модифікації має бути реалізований (навіть якщо він додає лише пару скобки), тоді як метод абстрактної модифікації не повинен бути реалізований. Наприклад, якщо метод віртуальної модифікації не реалізований:
Помилка: "Test1.fun1()" повинен декларувати тіло, оскільки воно не позначене як абстрактне, зовнішнє чи часткове
Для абстрактних модифікаторів, якщо вони реалізовані:
Помилка: "Test2.fun2()" не може оголосити тіло, оскільки воно позначене як абстрактне
(2) віртуальний можна переписати підкласами, тоді як абстрактний має переписуватися підкласами.
При компіляції немає помилки, якщо метод віртуального модифікатора переписується, перед ним потрібно додати перевизначення (що повідомляє компілятору, що ви хочете переписати віртуальний метод), і має бути реалізація, інакше компіляція буде неправильною:
(3) Якщо член класу модифікується абстрактним, абстрактний слід додати перед класом, оскільки лише абстрактні класи можуть мати абстрактні методи.
(4) Екземпляри абстрактних класів не можна створювати, їх можна лише успадкувати і не можна інстанціювати, наприклад: BaseTest2 base2 = новий BaseTest2(); Виникає помилка компіляції: Абстрактний клас або інтерфейс не може створити екземпляр.
(5) У C#, якщо ви хочете переписати метод у підкласі, потрібно додати virtual перед батьківським методом і перевизначити перед підкласом, щоб програмісти не переписували батьківський метод у підкласі.
(6) Абстрактний метод має бути перезаписаний, а віртуальний метод повинен мати реалізацію (навіть якщо це метод, визначений у абстрактному класі).
Інтерпретація 3 Схожості: 1. Всі вони можуть бути спадкові 2. Жоден із них не може бути реалізований 3. Він може містити оголошення методів 4. Похідні класи повинні реалізовувати нереалізовані методи Відрізнити: 1. Абстрактні базові класи можуть визначати поля, атрибути та реалізації методів. Інтерфейси можуть визначати лише атрибути, індексери, події та оголошення методів і не можуть містити поля. 2. Абстрактний клас — це неповний клас, який потребує подальшого уточнення, тоді як інтерфейс — це поведінкова норма. Власні інтерфейси Microsoft завжди мають поле для доведення здатності, що є вираженням «Я можу це зробити...» ” 3. Інтерфейси можуть бути реалізовані кілька разів, а абстрактні класи можуть успадковуватися лише однією людиною 4. Абстрактні класи більш визначені між низкою тісно пов'язаних класів, тоді як більшість інтерфейсів слабо пов'язані, але всі реалізують певну функцію 5. Абстрактні класи — це поняття, абстраговані з низки споріднених об'єктів, тому вони відображають внутрішню спільність речей; Інтерфейс — це функціональна конвенція, визначена для задоволення зовнішніх викликів, тому вона відображає зовнішні характеристики речей 6. Інтерфейс фактично не має жодних специфічних характеристик спадкування, він лише обіцяє метод, який можна викликати 7. Інтерфейс може використовуватися для підтримки зворотних викликів, але спадковість не має такої функції 8. Конкретні методи, реалізовані абстрактними класами, є віртуальними за замовчуванням, але методи інтерфейсу в класі, які реалізують інтерфейс, за замовчуванням не є віртуальними, звісно, їх також можна оголосити віртуальними 9. Якщо абстрактний клас реалізує інтерфейс, метод в інтерфейсі можна відобразити в абстрактний клас як абстрактний метод без необхідності його реалізувати, але метод в інтерфейсі може бути реалізований у підкласі абстрактного класу. Правила використання: 1. Абстрактні класи переважно використовуються для тісно пов'язаних об'єктів, тоді як інтерфейси найкраще для забезпечення загальної функціональності для нерелевантних класів 2. Якщо ви хочете спроектувати великий функціональний блок, використовуйте абстрактні класи; Якщо хочете проектувати невеликі, лаконічні функціональні блоки, використовуйте інтерфейси. 3. Якщо очікується створення кількох версій компонента, створіть абстрактний клас. Після створення інтерфейсу його не можна змінювати. Якщо потрібна нова версія інтерфейсу, потрібно створити абсолютно новий інтерфейс. 4. Якщо створена функція буде використовуватися між широким спектром гетерогенних об'єктів, використовуйте інтерфейс; Якщо ви хочете забезпечити спільну реалізовану функціональність для всіх реалізацій компонента, використовуйте абстрактні класи. 5. Проаналізувати об'єкт, уточнити внутрішню спільність, щоб сформувати абстрактний клас, який використовується для вираження сутності об'єкта, тобто «що». Інтерфейси мають пріоритет, коли потрібно розширити зовнішні виклики або функції 6. Хороше визначення інтерфейсу має бути специфічним і функціональним, а не багатофункціональним, інакше це призведе до забруднення інтерфейсу. Якщо клас реалізує лише одну функцію інтерфейсу, але має реалізувати інші методи в інтерфейсі, це називається забрудненням інтерфейсу 7. Намагайтеся уникати використання спадкування для досягнення функції формування, але використовуйте мультиплексування чорної скриньки, тобто комбінацію об'єктів. Через збільшення кількості рівнів спадкування найпрямішим наслідком є те, що коли ви викликаєте клас у цьому таксоні, потрібно завантажити їх усі в стек! Наслідки можна уявити. (У поєднанні з розумінням принципу стеку). Водночас зацікавлені друзі можуть помітити, що Microsoft часто використовує метод комбінації об'єктів при створенні класу. Наприклад, у asp.net клас Page має властивості, такі як Server Request, але насправді всі вони є об'єктами певного класу. Використання цього об'єкта класу Page для виклику методів і властивостей інших класів є дуже базовим принципом проєктування Наприклад: Форми вікон можна проектувати з абстрактними класами, а публічні операції та властивості розміщувати в абстрактному класі, щоб форма і діалогове вікно могли успадкувати від цього абстрактного класу, а потім розширюватися та вдосконалюватися відповідно до власних потреб.
Операція друку може бути використана як інтерфейс для кожної форми, яка потребує цієї функції, оскільки вміст форми відрізняється, і вони мають реалізувати власну функцію друку відповідно до власних вимог. Під час друку він викликається лише через інтерфейс, незалежно від форми друку.
Спільність, індивідуальність і вибір: Деякі книги пишуть, що C# рекомендує використовувати інтерфейси замість абстрактних базових класів, і підкреслює численні переваги використання інтерфейсів, з якими я не наважуюся заперечувати; з наведеного вище списку все ще існує багато відмінностей між ними, і їхнє існування має визначати різницю у відповідних сценаріях, наприклад, абстрактний базовий клас може надати стандартні реалізації для деяких методів, щоб уникнути повторної реалізації в підкласах і покращити повторне використання коду. Це перевага абстрактних класів; Інтерфейс може містити лише абстрактні методи. Щодо того, коли використовувати абстрактні базові класи, а коли — інтерфейси, це залежить від того, як користувачі сприймають зв'язки між успадкованими класами — чи це відмінності особистості, чи спільні зв'язки між ними. Дозвольте проілюструвати приклад із життя.
Якщо вам дають три об'єкти — люди, риби та жаби, і вас просять створити базову категорію для них, щоб підсумувати зв'язок між ними, то перше, що ви відчуєте — це великі відмінності між ними, і важко абстрагувати спільні риси. Ось тут варто розглянути використання інтерфейсів замість абстрактних базових класів з трьох причин:
1. Індивідуальність важливіша за спільність. 2. Особистості з великими відмінностями мають деякі схожі поведінкові риси. 3. Існують суттєві відмінності у методах реалізації однієї й тієї ж поведінки. У цей момент вам дають ще три об'єкти — карас, короп і золоту рибку, і ви все одно можете спроектувати базові класи, щоб узагальнювати зв'язок між ними. Перше, що ви розумієте, — що всі вони належать рибам, а по-друге, спосіб плавання може трохи відрізнятися, тому слід використовувати абстрактні базові класи замість інтерфейсів, порівняно з наведеним вище прикладом, є три причини:
1. Спільність більша за індивідуальність 2. Особи з однаковими спільними рисами повинні мати однакові риси та поведінку 3. Існують певні відмінності у методах реалізації однієї й тієї ж поведінки Серед кількох причин використання інтерфейсів або абстрактних базових класів третя причина, фактично та, що описує поняття поліморфізму в об'єктно-орієнтованому режимі, тобто реалізацію шляхом перевизначення батьківського класу та виклику відповідного методу під час виконання відповідно до переданого посилання на об'єкт. Друга причина починає розходитися: інтерфейси наголошують на однаковій поведінці між успадкованими об'єктами, тоді як абстрактні класи також наголошують на однакових властивостях між успадкованими об'єктами. Те, що справді відрізняє інтерфейси від абстрактних базових класів, полягає в наступних причинах:
Інтерфейси використовуються, коли шукають функціональну спільність між об'єктами з великими відмінностями. Абстрактні базові класи використовуються, коли шукають функціональні відмінності між об'єктами з більшою спільністю. Порівнюючи однакові та різні, можна лише сказати, що інтерфейси та абстрактні класи мають свої переваги, але жодних переваг. У реальній практиці програмування нам потрібно оцінювати наші таланти відповідно до конкретної ситуації, але наступний досвід і накопичення можуть надихнути вас, окрім частини мого накопичення, багато з них походять із класики, я вірю, що вони витримають випробування. Тож у правилах і заходах, коли ми вивчаємо ці класики, найважливіше — застосовувати те, що ми навчилися, звісно, я здобуду сміх усіх словами сім'ї, продовжуйте.
Правила та події: 1. Пам'ятайте, що одним із найважливіших принципів об'єктно-орієнтованого мислення є: інтерфейсно-орієнтоване програмування. 2. За допомогою інтерфейсів і абстрактних класів багато ідей у 23 шаблонах дизайну були вдало реалізовані, і я вважаю, що їхня суть просто в тому, що вони орієнтовані на абстрактне програмування. 3. Абстрактні класи слід використовувати переважно для тісно пов'язаних об'єктів, тоді як інтерфейси найкраще для забезпечення загальної функціональності для нерелевантних класів. 4. Інтерфейс зосереджується на типі відношення CAN-DO, тоді як абстрактний клас — на відношенні IS-A. 5. Поведінка багатовизначених об'єктів у інтерфейсі; абстрактні класи багатовизначають властивості об'єктів; 6. Визначення інтерфейсів можуть використовувати публічні, захищені, внутрішні та приватні модифікатори, але майже всі інтерфейси визначені як публічні, тому більше не потрібно пояснювати. 7. «Інтерфейс залишається незмінним» — важливий фактор, який слід враховувати. Тому при додаванні розширень з інтерфейсів слід додавати нові інтерфейси, а не існуючі. 8. Спробуйте спроектувати інтерфейс у функціональний блок з однією функцією, взявши за приклад .NET Framework, IDisposable, IDisposable, IComparable, IEquatable, IEnumerable тощо — усі вони містять лише один поширений метод. 9. Велика літера «I» перед назвою інтерфейсу є конвенцією, так само як і назва поля починається з підкреслення, будь ласка, дотримуйтесь цих принципів. 10. В інтерфейсі всі методи за замовчуванням стають публічними. 11. Якщо очікуються версійні задачі, можна створити «абстрактний клас». Наприклад, якщо ви створюєте собаку, курку та качку, варто розглянути абстрагування тварин, щоб впоратися з речами, які можуть виникнути в майбутньому. Додавання нових елементів до інтерфейсу змушує змінювати та компілювати всі похідні класи, тому задачі версування найкраще реалізовувати за допомогою абстрактних класів. 12. Неабстрактні класи, отримані з абстрактних класів, повинні включати всі успадковані абстрактні методи та фактичні реалізації абстрактних аксесорів. 13. Нове ключове слово не може використовуватися для абстрактних класів і не може бути запечатане, оскільки абстрактні класи не можуть бути інстанційовані. 14. Статичні або віртуальні модифікатори не можуть використовуватися в оголошеннях абстрактних методів.
|