Чому інтерфейси корисні?


158

Я вже деякий час вивчаю і кодую в C #. Але все-таки я не можу зрозуміти корисність інтерфейсів. Вони подають занадто мало до столу. Крім надання підписів функції, вони нічого не роблять. Якщо я можу запам'ятати імена та підписи функцій, які потрібно здійснити, то в них немає потреби. Вони там просто для того, щоб переконатися, що зазначені функції (в інтерфейсі) реалізовані в класі спадкування.

C # - чудова мова, але іноді створює відчуття, що спочатку Microsoft створює проблему (не допускаючи багаторазового успадкування), а потім надає рішення, яке є досить стомлюючим.

Це моє розуміння, яке базується на обмеженому досвіді кодування. Що ти береш за інтерфейси? Як часто ви використовуєте їх і що змушує вас це робити?


55
"Якщо я можу запам'ятати імена та підписи функцій, які потрібно реалізувати, в них немає потреби". Це твердження змушує мене підозрювати, що ви повинні трохи більше вивчити переваги мов, які мають статичний тип .
Стівен Євріс

37
Забудьте C #, забудьте Java, забудьте мову. Це просто мислення з точки зору ОО. Я б закликав вас взяти матеріал для читання у людей, таких як Роберт К. Мартін, Мартін Фаулер, Майкл Перо, Банда чотирьох тощо, оскільки це допоможе розширити ваше мислення.
Ентоні Пеграм

27
Мені знадобилося більше двох років, щоб зрозуміти, для чого хороші інтерфейси. Моя пропозиція: вивчіть шаблони дизайну. Оскільки більшість з них покладається на інтерфейси, ви швидко зрозумієте, чому вони такі корисні.
Олівер Вайлер

37
У тебе є багато чого навчитися друг.
ChaosPandion

60
@ChaosPandion у всіх нас є багато чого навчитися
kenwarner

Відповіді:


151

Вони там просто для того, щоб переконатися, що зазначені функції (в інтерфейсі) реалізовані в класі спадкування.

Правильно. Це достатньо приголомшлива користь для виправдання функції. Як говорили інші, інтерфейс - це договірне зобов'язання щодо реалізації певних методів, властивостей та подій. Переконлива перевага статично набраної мови полягає в тому, що компілятор може перевірити, чи дійсно виконується договір, на який покладається ваш код.

Однак, інтерфейси є досить слабким способом представлення договірних зобов'язань. Якщо ви хочете більш сильно та гнучкіше представляти договірні зобов'язання, перегляньте функцію Код контрактів, що постачається з останньою версією Visual Studio.

C # - чудова мова, але коли-небудь створює відчуття, що спочатку Microsoft створює проблему (не допускаючи багаторазового успадкування), а потім надає рішення, яке є досить стомлюючим.

Ну я радий, що тобі це подобається.

Усі складні розробки програмного забезпечення є результатом зважування суперечливих особливостей один проти одного та намагання знайти «солодке місце», яке дає великі переваги за невеликих витрат. За допомогою болісного досвіду ми дізналися, що мови, які дозволяють отримати багато успадкованих цілей для цілей спільного використання, мають відносно невеликі переваги та відносно великі витрати. Дозвіл багаторазового успадкування лише на інтерфейсах, які не поділяють деталі реалізації, дає багато переваг багаторазового успадкування без більшості витрат.


Я просто читав "Microsoft створює проблему, не даючи багаторазового успадкування", і думав, що Ерік Ліпперт буде про що сказати.
конфігуратор

Більш відповідна для цієї відповіді: Еріку, ти звертаєш запитувача до Код-контрактів, але вони жахливо неповні; нічого, крім самих основних договорів, не виконує статична перевірка. Я спробував використовувати Код-контракт у невеликому проекті; Я додав сотні рядків для кожного методу, вказуючи все, що я міг щодо введення та виводу, і все ж, мені довелося додати стільки Assumeвикликів, для таких випадків, як члени масиву чи перерахування. Додавши все і побачивши в мене статично перевірений безлад, я повернувся до контролю джерел, оскільки це знизило якість мого проекту.
конфігуратор

17
@configurator: Вони неповні, оскільки не можуть бути завершеними; статична перевірка програми за допомогою довільних контрактів рівнозначна вирішенню проблеми зупинки. (Наприклад, ви можете написати контракт з кодом, який говорить про те, що аргументи методу повинні бути контрприкладом до Останньої теореми Ферма; але статичний верифікатор не зможе перевірити, чи немає таких аргументів.) Ви повинні використовувати його розумно, якщо очікуєте, що статичний перевіряльник завершить свою роботу до теплової загибелі Всесвіту. (Якщо у вас є скарга на те, що BCL недостатньо зазначається: я згоден.)
Ерік Ліпперт,

2
Я очікую, що він зрозуміє, що коли один метод обіцяє, що масив результатів чи перерахування не містить нульових значень, використовуючий метод може використовувати значення в місцях, які не дозволяють нулю. Це одне, що я очікував, що він це зробить, а це було занадто важливо, щоб бути без нього корисним; все інше - це лише бонус. Однак, я знаю, що статична перевірка не може бути повною, тому я вважаю, що це не є хорошою альтернативою покладатися на контракти.
конфігуратор

9
+1 за "Ну, я радий, що тобі це подобається". І всі інші речі теж.
Роберт С.

235

введіть тут опис зображення

Отже, у цьому прикладі PowerSocket нічого іншого не знає про інші об'єкти. Усі об'єкти залежать від потужності, що надається PowerSocket, тому вони реалізують IPowerPlug, і таким чином вони можуть підключитися до нього.

Інтерфейси корисні, оскільки вони надають договори, які об’єкти можуть використовувати для спільної роботи, не потребуючи нічого іншого знати.


4
Лівий нижній об’єкт не схожий на реалізацію IPowerPlug =)
Стівен Стрига

100
Чорт, але для використання IPowerPlug в різних країнах нам доведеться використовувати модель адаптера!
Стівен Євріс

Джеррі-такелаж пристрою для обходу інтерфейсу не є безпечним (але деякі люди все ще роблять це, часто називаючи продуктивність неперевіреною виправданням) і, ймовірно, може призвести до пожеж.
YoungJohn

4
Ця відповідь просто дивовижна ...
Маріо Гарсія

Тільки вказуючи на цю відповідь, у цьому конкретному прикладі не сказано, чому використання інтерфейсу було б кращим перед успадкуванням. Хтось, хто не знає інтерфейсів, може запитати, чому вони не просто успадковують, наприклад, MainsPoweredDevice, який забезпечує всю функціональність штекера, при цьому сокет приймає все, що походить від MainsPoweredDevice.
інгредієнт_15939

145

Крім надання підписів функції, вони нічого не роблять. Якщо я можу запам'ятати імена та підписи функцій, які потрібно здійснити, то в них немає потреби

Суть інтерфейсів - це не допомогти вам запам’ятати, який метод реалізувати, саме тут потрібно визначити договір . На прикладі P.Brian.Mackey (який виявляється невірним , але нам все одно), IEnumerable визначає контракт між foreach і будь-якою численною річчю. У ньому сказано: "Хто б ви не були, поки ви дотримуєтесь договору (виконайте IEnumerable), я обіцяю вам, що я перейматиму всі ваші елементи". І це чудово (для нединамічної мови).

Завдяки інтерфейсам ви можете досягти дуже низької зв'язку між двома класами.



Мені не подобається використовувати термін «качка набором», оскільки це означає різні речі для різних людей. Ми використовуємо відповідність шаблону для циклу "foreach", оскільки при його розробці IEnumerable <T> був недоступний. Ми використовуємо відповідність шаблонів для LINQ, оскільки система типу C # занадто слабка, щоб захопити потрібний нам "монадовий шаблон"; вам знадобиться щось на зразок системи типу Haskell.
Ерік Ліпперт

@Eric: Невже "відповідність шаблону" не має тієї ж проблеми? Коли я чую це, я думаю, що F # / Scala / Haskell. Але я здогадуюсь, це більш широка ідея, ніж набирання качок.
Даніель

@Daniel: Так, я вважаю, що так і є. Я здогадуюсь про шість з півтора десятка іншого!
Ерік Ліпперт

36

Інтерфейси - найкращий спосіб підтримувати добре відокремлені конструкції.

Під час написання тестів ви побачите, що конкретні заняття не працюватимуть у вашому тестовому середовищі.

Приклад: Ви хочете протестувати клас, який залежить від класу служби доступу до даних . Якщо цей клас розмовляє з веб-службою або базою даних - ваш тест одиниці не буде працювати у вашому тестовому середовищі (плюс він перетворився на тест інтеграції).

Рішення? Використовуйте інтерфейс для служби доступу до даних та знущайтеся над цим інтерфейсом, щоб ви могли перевірити свій клас як одиницю.

З іншого боку, WPF & Silverlight взагалі не грають з інтерфейсами, коли мова йде про прив'язку. Це досить неприємна зморшка.


2
чути чути! Інтерфейси були винайдені для вирішення інших проблем, таких як поліморфізм. Однак, для мене, вони вступають у свої власні сили, коли реалізують модель введення залежностей.
Енді

29

Інтерфейси є основою (статичного) поліморфізму! Інтерфейс - це важливо. Спадкування не працювало б без інтерфейсів, оскільки підкласи в основному успадковують вже реалізований інтерфейс батьків.

Як часто ви використовуєте їх і що змушує вас це робити ??

Досить часто. Все, що потрібно підключити - це інтерфейс у моїх програмах. Часто у вас є не пов’язані між собою заняття, яким потрібно надати однакову поведінку. Ви не можете вирішити такі проблеми із спадщиною.

Потрібні різні алгоритми для виконання операцій над одними і тими ж даними? Використовуйте інтерфейс ( див. Шаблон стратегії )!

Ви хочете використовувати різні реалізації списків? Код проти інтерфейсу і абоненту не потрібно турбуватися про реалізацію!

Вважається хорошою практикою (не тільки в OOP) кодувати проти інтерфейсів на віки з однієї єдиної причини: легко змінити реалізацію, коли зрозумієш, що вона не відповідає вашим потребам. Це досить громіздко, якщо ви намагаєтеся досягти цього лише при багатократному успадкуванні, або це зводиться до створення порожніх класів, щоб забезпечити необхідний інтерфейс.


1
Ніколи не чули про поліморфію, ви маєте на увазі поліморфізм?
Стівен Євріс

1
якщо сказати, якби Microsoft вперше дозволив успадкувати багато разів, не було б ніяких причин для існування інтерфейсів
Pankaj Upadhyay

10
@Pankaj Upadhyay: Багаторазове успадкування та інтерфейси - це дві різні пари взуття. Що робити, якщо вам потрібен інтерфейс двох непов'язаних класів з різною поведінкою? Ви не можете вирішити це шляхом багатократного успадкування. Ви ВІДБУДЕТЕ це реалізувати окремо. І тоді вам знадобиться щось для опису інтерфейсу, щоб забезпечити поліморфну ​​поведінку. Багатократне успадкування - це сліпа алея, яку можна спустити в багатьох випадках, і занадто легко рано чи пізно стріляти в ногу.
Сокіл

1
Давайте спростимо. Якщо мій інтерфейс реалізує дві функції Display і Comment, і у мене є клас, який їх реалізує. Тоді чому б я не видалити інтерфейс і використовувати функції безпосередньо. Що я говорю, це те, що вони просто дають вам назви функцій, які потрібно здійснити. Якщо ви можете згадати ці функції, то навіщо створювати інтерфейс
Панкай Упадхей

9
@Pankaj, якщо це все, що вам потрібно для інтерфейсу, тоді не використовуйте його. ВИ використовуєте інтерфейс, коли у вас є програма, яка хоче не знати всіх аспектів класу і отримувати доступ до нього за його базовим типом, тобто інтерфейсом. Їм не потрібно знати жодного з підкласів, лише той тип інтерфейсу. Тоді ви можете викликати реалізований метод підкласу через посилання на інтерфейс об'єкта. Це основні речі щодо спадкування та дизайну. Без нього ви можете також використовувати C. Навіть якщо ви прямо не використовуєте його, без нього рамки не працюватимуть.
Джонатан Хенсон

12

Ви, напевно, використовували foreachі вважали, що це досить корисний інструмент ітерації. Чи знаєте ви, що для його функціонування потрібен інтерфейс, численні ?

Це, безумовно, конкретний випадок, що говорить про корисність інтерфейсу.


5
Насправді, foreach не вимагає IEnumerable: msdn.microsoft.com/en-us/library/9yb8xew9%28VS.80%29.aspx
Matt H

1
Я все це вивчив, але це як би тримати вухо іншою рукою. Якби було дозволено багатократне успадкування, інтерфейс був би далеко вибором.
Pankaj Upadhyay

2
Інтерфейси - це багаторазове успадкування, що часто забувається. Однак вони не допускають багаторазового успадкування поведінки та стану. Міксини або риси дозволяють багатократно успадковувати поведінку, але не спільний стан, що спричиняє проблеми: en.wikipedia.org/wiki/Mixin
Метт H

@Pankaj, офтопік, але чи не заперечуєш, якщо я запитую, яка твоя рідна мова? "Тримати вухо іншою рукою" - це чудова ідіома, і мені було цікаво, звідки воно береться.
Кевін

3
@Iceman. LOL .... Я з Індії. І ось це загальна ідіома, яка відображає робити легкі справи складним способом.
Pankaj Upadhyay

11

Інтерфейси призначені для кодування об'єктів, таких як штепсельна розробка для побутової проводки. Ви б припаяли радіо безпосередньо на проводку будинку? Як щодо вашого пилососа? Звичайно, ні. Вилка та розетка, в яку вона вписується, утворюють "інтерфейс" між проводкою вашого будинку та пристроєм, який потребує від нього живлення. Проводка вашого будинку не повинна нічого знати про пристрій, окрім як він використовує трижильний заземлений штепсель і потребує електричної потужності при 120 В змінного струму <= 15А. І навпаки, пристрій не вимагає прихованих знань про те, як проводять ваш будинок, за винятком того, що він має одну або кілька трикутних розеток, зручно розташованих, що забезпечують 120В переменного току <= 15А.

Інтерфейси виконують дуже схожу функцію в коді. Об'єкт може оголосити, що певна змінна, параметр або тип повернення мають тип інтерфейсу. Інтерфейс не може бути використаний безпосередньо за допомогою newключового слова, але моєму об’єкту можна надати або знайти реалізацію того інтерфейсу, з яким йому потрібно буде працювати. Після того, як об'єкт має свою залежність, він не повинен точно знати, що це за залежність, він просто повинен знати, що він може викликати методи X, Y і Z від залежності. Реалізація інтерфейсу не повинна знати, як вони будуть використовуватися, вони просто повинні знати, що від них потрібно буде забезпечити методи X, Y і Z з певними підписами.

Таким чином, абстрагуючи кілька об'єктів за одним інтерфейсом, ви надаєте загальний набір функціональних можливостей будь-якому споживачеві об'єктів цього інтерфейсу. Ви не повинні знати, що об'єктом є, наприклад, Список, Словник, LinkedList, OrdersList тощо. Оскільки ви знаєте, що все це IEnumerables, ви можете використовувати методи IEnumerable, щоб переглядати кожен елемент цих колекцій по одному. Вам не потрібно знати, що вихідний клас - це ConsoleWriter, FileWriter, NetworkStreamWriter або навіть MulticastWriter, який приймає інші типи авторів; все, що вам потрібно знати, це те, що вони всі IWriters (або що завгодно), і, таким чином, у них є метод "Write", в який ви можете передати рядок, і ця рядок буде виведена.


7

Незважаючи на те, що програміст (спочатку, щонайменше, є нагодою мати багатократне успадковування), це майже тривіальний недолік, і вам слід (у більшості випадків) не покладатися на багаторазове успадкування. Причини цього складні, але якщо ви дійсно хочете дізнатися про це, врахуйте досвід двох найвідоміших (за індексом TIOBE ) мов програмування, які її підтримують: C ++ та Python (3-й та 8-й респектабельно).

У Python підтримується багатократне успадкування, але програмісти майже не розуміють загалом, і заявити, що ви знаєте, як це працює, означає прочитати та зрозуміти цю статтю на тему: Порядок вирішення методу . Щось інше, що трапляється в Python, - це те, що інтерфейси, начебто потрапили в мову - Zope.Interfaces.

Для C ++, google "алмазна ієрархія C ++", і ось потворність, яка ось-ось охопить вас. Професіонали C ++ знають, як використовувати множинне успадкування. Всі інші зазвичай просто розігруються, не знаючи, які будуть результати. Ще одна річ, яка показує, наскільки корисні інтерфейси, - це той факт, що у багатьох випадках класу може знадобитися повністю перекрити поведінку батьків. У таких випадках батьківська реалізація є непотрібною і лише обтяжує дочірній клас пам'яттю для приватних змінних батьків, які можуть не мати значення для віку C #, але мають значення, коли ви робите вбудоване програмування. Якщо ви використовуєте інтерфейс, ця проблема відсутня.

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

Крім того, історично склалося, що ідея інтерфейсу коріняється набагато раніше, ніж технічні характеристики C # Microsoft. Більшість людей вважають C # оновленням над Java (у більшості почуттів), і здогадуються, звідки C # отримав свої інтерфейси - Java. Протокол - це старше слово для тієї ж концепції, і воно набагато старше, ніж .NET.

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


6

Мені важко уявити чистий об'єктно-орієнтований код C # без використання інтерфейсів. Ви використовуєте їх, коли хочете забезпечити наявність певної функціональності, не примушуючи класи успадковувати певний базовий клас, і це дозволяє вашому коду мати відповідний рівень (низького) зв'язку.

Я не погоджуюся, що багатократне успадкування краще, ніж мати інтерфейси, навіть перш ніж ми доводимось до того, що багаторазове успадкування має власний набір болів. Інтерфейси - це основний інструмент для поліморфізму та повторного використання коду, що ще потрібно?


5

Я особисто люблю абстрактний клас і використовую його більше, ніж інтерфейс. Основна відмінність полягає в інтеграції з .NET інтерфейсами, такими як IDisposable, IEnumerable і так далі ... і з COM interop. Крім того, інтерфейс трохи менше зусиль для запису, ніж абстрактний клас, і клас може реалізувати більше одного інтерфейсу, в той час як він може успадковувати лише один клас.

З цього приводу я вважаю, що більшість речей, для яких я б використовував інтерфейс, краще обслуговуються абстрактним класом. Чисті віртуальні функції - абстрактні функції - дозволяють змусити виконавця визначити функцію, аналогічну тому, як інтерфейс змушує виконавця визначати всіх його членів.

Тим не менш, ти зазвичай використовуєш інтерфейс, коли ти не хочеш накладати певний дизайн супер-класу, тоді як ти будеш використовувати абстрактний клас, щоб мати багаторазовий дизайн, який вже в основному реалізований.

Я широко використовував інтерфейси для написання середовищ плагінів, використовуючи простір імен System.ComponentModel. Вони дуже корисні.


1
Дуже добре кажучи! Я здогадуюсь, що вам сподобається моя стаття про абстрактні класи. Абстракція - це все .
Стівен Євріс

5

Я можу сказати, що я до цього ставлюсь. Коли я вперше почав вивчати OO та C #, я теж не отримав інтерфейсів. Це добре. Нам просто потрібно натрапити на щось, що змусить вас оцінити зручності інтерфейсів.

Дозвольте спробувати два підходи. І вибачте мене за узагальнення.

Спробуйте 1

Скажіть, ви є носієм англійської мови. Ви їдете в іншу країну, де англійська мова не є рідною мовою. Тобі потрібна допомога. Вам потрібен хтось, хто може вам допомогти.

Ви запитаєте: "Гей, ти народився в США?" Це спадщина.

Або ви запитуєте: "Гей, ти розмовляєш англійською"? Це інтерфейс.

Якщо ви дбаєте про те, що це робить, ви можете покластися на інтерфейси. Якщо ви дбаєте про те, що є, ви покладаєтесь на спадщину.

Добре покладатися на спадщину. Якщо вам потрібен хтось, хто розмовляє англійською, любить чай і любить футбол, вам краще подавати британку. :)

Спробуйте 2

Гаразд, спробуємо ще один приклад.

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

public abstract class SuperDatabaseHelper
{
   void Connect (string User, string Password)
}

public abstract class HiperDatabaseHelper
{
   void Connect (string Password, string User)
}

Кажете, багатократна спадщина? Спробуйте це у наведеному вище випадку. Ви не можете. Компілятор не дізнається, який метод Connect ви намагаєтеся зателефонувати.

interface ISuperDatabaseHelper
{
  void Connect (string User, string Password)
}

interface IHiperDatabaseHelper
{
   void Connect (string Password, string User)
}

Тепер є щось, з чим ми можемо працювати - принаймні, на C # - де ми можемо чітко реалізувати інтерфейси.

public class MyDatabaseHelper : ISuperDatabaseHelper, IHiperDatabaseHelper
{
   IHiperDataBaseHelper.Connect(string Password, string User)
   {
      //
   }

   ISuperDataBaseHelper.Connect(string User, string Password)
   {
      //
   }

}

Висновок

Приклади не найкращі, але я думаю, що це балотується в цілому.

Інтерфейси ви "отримаєте" лише тоді, коли відчуєте потребу в них. Поки ви не подумаєте, що вони не для вас.


Перша спроба - це те, що дало мій голос.
osundblad

1
Відтепер я повністю використовую аналогію американського проти англійського спікера. Це фантастично.
Брайан Боттчер

Пояснюється більш простим способом! Фантастичний.
Аймал Хан

4

Є дві основні причини:

  1. Відсутність багаторазового успадкування. Ви можете успадкувати від одного базового класу та реалізувати будь-яку кількість інтерфейсів. Це єдиний спосіб "зробити" багатократне успадкування в .NET.
  2. Оперативна сумісність COM. Все, що буде потрібно використовувати "старіші" технології, має мати визначені інтерфейси.

Точка 1, безумовно, є причиною і причиною, яку розробили самі розробники
мікрософт

1
@Pankja Насправді вони взяли ідею інтерфейсу від Java (як і хороша частина функцій C #).
Олівер Вайлер

3

Використання інтерфейсів допомагає системі залишатися нерозділеною і, таким чином, легше переробляти, змінювати та повторно використовувати. Це дуже основна концепція об'єктно-орієнтованої ортодоксальності, і я вперше дізнався про неї, коли гуру С ++ створили "чисті абстрактні класи", цілком еквівалентні інтерфейсам.


Розв'язка важлива, оскільки вона підтримує різні компоненти системи незалежно одна від одної. Навіть великі наслідки змін одного компонента не поширюються на інші компоненти. Подумайте про вилки живлення як інтерфейс для вашої комунальної компанії (вказавши напругу та фізичні штифти та формат штекера). Завдяки цьому інтерфейсу утиліта може повністю змінити спосіб їх виробництва (наприклад, використовувати сонячну технологію), але жоден з пристроїв навіть не помітить, не кажучи вже про зміну.
miraculixx

3

Інтерфейси самі по собі не дуже корисні. Але коли реалізуються конкретні класи, ви бачите, що це дає вам гнучкість мати одну чи більше реалізацій. Бонус полягає в тому, що об’єкту, що використовує інтерфейс, не потрібно знати, як проходять деталі фактичної реалізації - це називається інкапсуляція.


2

В основному вони використовуються для повторного використання коду. Якщо ви кодуєте інтерфейс, ви можете використовувати різний клас, який успадковується від цього інтерфейсу і не розбивати все.

Крім того, вони дуже корисні у веб-сервісах, де ви хочете повідомити клієнту, що робить клас (щоб він міг його споживати), але не хочете надати їм фактичний код.


2

Як молодий програміст / розробник, просто вивчаючи C #, ви, можливо, не бачите корисності інтерфейсу, оскільки ви можете писати свої коди за допомогою класів, і код прекрасно працює, але в реальному сценарії побудова масштабованого, надійного та бездоганного додатку передбачає використання Деякі архітектурні та шаблони, які можна зробити можливими лише за допомогою інтерфейсу, наприклад, є введення залежності.


1

Реальна реалізація світу:

Ви можете передавати об'єкт як тип інтерфейсу:

IHelper h = (IHelper)o;
h.HelperMethod();

Можна створити список інтерфейсу

List<IHelper> HelperList = new List<IHelper>();

За допомогою цих об'єктів ви можете отримати доступ до будь-якого з методів або властивостей інтерфейсу. Таким чином ви можете визначити інтерфейс для вашої частини програми. І побудувати логіку навколо цього. Тоді хтось інший може реалізувати ваш інтерфейс у своїх бізнес-об'єктах. Якщо зміни BO, вони можуть змінити логіку для компонентів інтерфейсу і не вимагати зміни логіки для вашого фрагмента.


0

Інтерфейси надають модульність модуля, надаючи механізм для класів для розуміння (та підписки) певних типів повідомлень, які постачає ваша система. Я докладу.

У своїй заявці ви вирішите, що кожного разу, коли форма завантажується або перезавантажується, ви хочете очистити всі речі, на яких розміщено хостинг. Ви визначаєте IClearінтерфейс, який реалізує Clear. Крім того, ви вирішуєте, що кожен раз, коли користувач натискає кнопку збереження, форма повинна намагатися зберігати свій стан. Таким чином, все, що перебуває, ISaveотримує повідомлення про збереження свого стану. Звичайно, практично кажучи, більшість інтерфейсів обробляють кілька повідомлень.

Що відрізняє інтерфейси, це те, що спільна поведінка може бути досягнута без успадкування. Клас, який реалізує даний інтерфейс, просто розуміє, як поводитися при видачі команди (повідомлення команди) або як відповісти при запиті (повідомлення запиту). По суті, класи у вашій програмі розуміють повідомлення, які надає ваша програма. Це полегшує побудову модульної системи, в яку можна включити речі.

У більшості мов існують механізми (наприклад, LINQ ) для запиту речей, які містяться в інтерфейсі. Зазвичай це допоможе вам усунути умовну логіку, оскільки вам не доведеться розповідати різні речі (які не є необхідними для одного і того ж ланцюжка спадкування), як вести себе аналогічно (відповідно до певного повідомлення). Натомість ви збираєте все, що розуміє певне повідомлення (дотримується інтерфейсу) і публікуєте повідомлення.

Наприклад, ви можете замінити ...

Me.PublishDate.Clear()
Me.Subject.Clear()
Me.Body.Clear()

... з:

For Each ctl As IClear In Me.Controls.OfType(Of IClear)()
    ctl.Clear()
Next

Це ефективно звучить як:

Слухай, чуєш! Чи будь-хто, хто розуміє очищення, будь ласка, Clearзараз!

Таким чином, ми можемо програмно уникати того, щоб говорити про кожну річ, щоб очистити себе. І коли в майбутньому додаються очищувані елементи, вони просто відповідають без додаткового коду.


0

Далі йде псевдокод:

class MyClass{

    private MyInterface = new MyInterfaceImplementationB();

    // Code using Thingy 

}

interface MyInterface{

    myMethod();

}

class MyInterfaceImplementationA{ myMethod(){ // method implementation A } }

class MyInterfaceImplementationB{ myMethod(){ // method implementation B } }

class MyInterfaceImplementationC{ myMethod(){ // method implementation C } }

Останні класи можуть бути абсолютно різними реалізаціями.

Якщо неможливо багаторазове успадкування, успадкування нав'язує реалізацію батьківського класу, що робить речі більш жорсткими. Програмування проти інтерфейсів, з іншого боку, може дозволити вашому коду або рамки бути надзвичайно гнучкими. Якщо ви коли-небудь стикаєтеся з випадком, коли хотіли, щоб ви могли обмінятись класами у ланцюжку спадкування, ви зрозумієте, чому.

Наприклад, рамка, яка забезпечує Reader, спочатку призначений для зчитування даних з диска, може бути повторно реалізована, щоб зробити щось такого ж характеру, але зовсім іншим способом. Наприклад, інтерпретувати код Морзе.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.