Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
веб.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
933.89 Кб
Скачать

3.4.3 Інтерфейси

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

public interface IDisposable

{

void Dispose();

}

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

Ім'я інтерфейсу традиційно починається з букви I, щоб відразу було зрозуміло, що це інтерфейс.

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

IBankAccount venusAccount = new SaverAccount();

IBankAccount jupiterAccount = new GoldAccount();

Інтерфейси можуть бути унаслідувані один від одного - точно так само, як класи.

namespace Wrox.ProCSharp

{

public interface ITransferBankAccount: IBankAccount

{

bool TransferTo(IBankAccount destination, decimal amount);

}

}

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

 

3.5Узагальнення

 

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

Інший спосіб скорочення обсягу коду - використання класу Object. Однак його застосування не забезпечує безпеки типів. Узагальнені класи працюють з узагальненими типами, замість яких при необхідності підставляються конкретні. Це забезпечує безпеку типів: компілятор повідомляє, коли певний конкретний тип не підтримується узагальненим класом.

Нижче наведено основні переваги і недоліки узагальнень:

        продуктивність;

        безпека типів;

        повторне використання двійкового коду;

        "розбухання" коду;

Продуктивність

Однією з основних переваг узагальнень є продуктивність. Використання типів значень з не узагальненими класами колекцій викликає упаковку (boxing) і розпаковку (unboxing) при перетворенні у контрольний тип і назад. Перетворення типу значень у контрольний тип називається упаковкою (boxing). Упаковка відбувається автоматично, коли метод очікує параметр типу посилань, а йому передається тип значень. З іншого боку упакований тип значень може бути назад перетворений до простого типу значень за допомогою розпакування (unboxing). При розпакуванні потрібна операція приведення.

Упаковку і розпаковування застосовувати легко, але вони сильно впливають на продуктивність, особливо при виконанні ітерацій по великій кількості елементів.

Замість використання об'єктів клас List <T> з простору імен System.Collections.Generic дозволяє визначити тип елементу при створенні колекції. Якщо узагальнений тип (тип-параметр) класу List<T> визначається як int, тому всередині динамічно згенерованого JIT-компілятором класу застосовується тип int, без будь-яких перетворень. Упаковка та розпаковка не потрібні.

var list = new List<int>();

list.Add(4); //ніякої упаковки

Безпека типів

Іншою властивістю узагальнень є безпека типів. При використанні узагальненого класу List <T> узагальнений тип-параметр Т задає тип елементів, який допускається вставляти в колекцію.

var list = new List <int> ();

list.Add(4);

list. Add(“mystring”); //помилка компіляції

Повторне використання двійкового коду

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

"Розбухання" коду

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

Нижче представлені рекомендації по іменування узагальнених типів.

        Імена узагальнених типів повинні починатися з букви Т.

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

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

Узагальнені класи

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

Узагальненому типу не можна присвоювати null. Причина в тому, що узагальнений тип дозволяє створювати екземпляр як типу значення, a null допускається тільки для типів посилань. Щоб усунути цю проблему, слід скористатися ключовим словом default. За допомогою ключового слова default типам посилань присвоюються значення null, а типам значень - 0.

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

public class DocumentManager <TDocument>

where TDocument: IDocument

{

Узагальнення підтримують кілька інших типів обмежень, таких як: struct, class, IFoo, Foo, new(), T2. З узагальненим типом можна також комбінувати безліч обмежень.

Узагальнений тип може реалізувати узагальнений інтерфейс. Те ж саме можливо за рахунок успадкування від класу. Узагальнений клас може бути успадкований від узагальненого базового класу:

public class Base <T>

{

public class Derived <T>: Base <T>

{

}

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

Статичні члени узагальненого класу розділяються тільки одним екземпляром класу.

Подібно до класів, структури також можуть бути узагальненими. Вони дуже схожі на узагальнені класи, за винятком можливості наслідування.

Узагальнені інтерфейси

Застосовуючи узагальнення, можна визначати інтерфейси, щоб вони оголошували методи з узагальненими параметрами. У .NET пропонується безліч узагальнених інтерфейсів для різних сценаріїв; до прикладів можна віднести IComparable<T>, ICollection<T> і IExtensibleObject<T>.

У .NET 4 з'явилося важливе розширення для узагальнених інтерфейсів і узагальнених делегатів - коваріантність і контрваріантність. Узагальнений інтерфейс коваріантний, якщо узагальнений тип анотований ключовим словом out. Це означає, що тип Т дозволений тільки в якості типу повернення. Узагальнений інтерфейс контрваріантний, якщо узагальнений тип анотований ключовим словом in. Таким чином, інтерфейс дозволяє використовувати узагальнений тип Т тільки в якості вхідного для своїх методів.

Узагальнені методи

На додаток до узагальнених класів можна також визначати узагальнені методи. В оголошенні узагальненого методу присутній узагальнений тип. Узагальнені методи можуть бути визначені всередині неузагальнених класів.

Узагальнений метод може бути викликаний із зазначенням конкретного типу замість узагальненого:

int i = 4;

int j = 5;

Swap <int> (ref i, ref j);

Однак оскільки компілятор С # може отримати тип для підстановки з типу параметрів, вказувати його при виклику такого методу не обов'язково. Узагальнений метод може бути викликаний точно так само, як простий неузагальнений.

Tі ж обмеження, які використовуються з узагальненими класами, можуть бути застосовані і до узагальнених методів. Узагальнені методи можуть бути перевантажені для визначення спеціалізацій певних типів. Це також вірно і для узагальнених параметрів.

 

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]