Интерфейсы Обобщения ( шаблоны ) Лекция 4
Интерфейсы Обобщения
Интерфейсы Обобщения
Интерфейс - контракт, поведение, которое реализующий класс обязуется поддерживать. Набор семантически связанных абстрактных членов. Интерфейс определяет спецификацию, но не определяет реализацию Класс – наследуют, а интерфейс – реализуют
Объявление интерфейса interface [attributes] [modifiers] interface interface_name [: base_interfaces] { interface_body } Пример объявления интерфейса public interface IDisposable { void Dispose(); } public interface IPointy { byte Points {get;} int GetNumberOfPoints(); }
Интерфейс может содержать следующие члены Методы Свойства Индексаторы События Не могут содержать поля Не могут содержать реализацию Члены интерфейса не могут быть статическими Члены интерфейса не могут иметь модификаторов Члены интерфейса всегда public
Классы и структуры могут реализовать интерфейсы public class Circle2d : Ellipse2d, ICloneable Базовый класс должен идти первым в списке, а за ним список реализуемых интерфейсов. Можно реализовать одновременно несколько интерфейсов Класс, реализующий интерфейс : Либо реализует все его методы Либо объявляет их ( и себя ) абстрактными
Неявная реализация интерфейса Записывается короткое имя каждого метода public object Clone() { … } Метод доступен как обычноperemen.Clone() Метод доступен и через интерфейс (( ICloneable)peremen).Clone() Явная (explicit) реализация интерфейса Записывается квалифицированное имя каждого метода object ICloneable.Clone() { … } Метод доступен только через интерфейс (( ICloneable)peremen).Clone() Используется при наличии конфликта Не указывается модификатор доступа. Он неявно public
Привязка к не виртуальным методам Производному классу, чтобы сменить реализацию, требуется самому реализовать интерфейс Привязка к виртуальным методам Производным классам достаточно просто переопределить виртуальный метод, чтобы сменить реализацию
Интерфейсы могут наследоваться от других интерфейсов. Производный интерфейс включает в себя все из базовых интерфейсов Тип ( класс, структура ), реализующие производный интерфейс должен реализовать также и все базовые интерфейсы public interface IDrawable : IPrintable {} Передача интерфейсов в качестве параметров Метод принимает любой тип, реализующий данный интерфейс public void GetShape(IDrawable shape); Интерфейсы в качестве возвращаемых параметров Метод возвращает некий тип, который реализует данный интерфейс public IDrawable GetShape(); I В.NET все существующие интерфейсы начинаются с I
Абстрактные классы и интерфейсы обеспечивают абстракцию Абстрактные классы могут содержать реализацию, интерфейсы – нет Интерфейсы могут содержать только методы, свойства, события и индексаторы Все члены интерфейса – public. Это открытый контракт Используйте абстрактные классы, если : Требуется определить определенную функциональность, которую могут использовать все наследники Производный класс является базовым Используйте интерфейсы Производный класс реализует интерфейс Требуется множественное наследование
ICloneable Определяет единственный метод object Clone() Позволяет выполнять копирование объектов IDisposable Определяет единственный метод Dispose() Реализуйте этот метод, если требуется освобождение внешних ресурсов Файлы, соединения и т. д. IComparable – используется при сортировках при сравнении 2 элементов IEnumerable, IEnumerable, IEnumerator, IEnumerator Позволяют итерировать по коллекции IDictionary, IList, ICollection Интерфейсы реализуемые коллекциями
Интерфейсы
Реализуйте абстрактный класс Shape, содержащий метод Draw(), якобы рисующий фигуру ( вывод строки на экран ) Создайте классы его потомков Triangle, Hexagon, Circle, Sphere Создайте интерфейсы IPoint, со свойством Point, выдающим количество точек в фигуре. IDrawable, с методом Draw(), якобы рисующем фигуру ( вывод строки на экран ) Реализуйте IPoint для Triangle и Hexagon IDrawable для Triangle ( не явно ) и Sphere ( явно ) В основном классе : Создайте метод AnalyzeShape(), принимающий Shape и распечатывающий, если возможно, кол - во точек в фигуре, и вызывающий метод Draw напрямую и через интерфейс. В методе Main создайте массив из Shape с разными фигурами и проанализируйте их вызвав метод AnalyzeShape()
Интерфейсы Обобщения
Тип, метод или интерфейс параметризованны другим типом Обобщенный тип Тип ( класс, структура ), который параметризован другим типом class Queue { } struct Complex { } Обобщенная функция Функция, параметром которой является тип T Swap (T x, T y) { } Обобщенный делегат Делегат, параметрами которого являются типы delegate T MyDelegate () where T : new() Обобщенный интерфейс interface IEnumerable { }
Не типизированные коллекции Один код для всех Нет контроля типов, накладные расходы Коллекции с жёстко заданным типом Каждый раз новый код Контроль типов, нет накладных расходов Обобщенные коллекции Один код для всех Контроль типов, нет накладных расходов
[Модификаторы] class ИмяКласса [Ограничения типов] {…} ОбозначенияТипов := Обозначение1 [,ОбозначениеN] Ограничения типов := where ОбозначениeТипа1 : ограничения [, ОбозначениeТипаN : ограниченияN] Пример : public class Stack T where T : IDisposable, new() { T T[] arr; TT T top = default(T); TT T example = new T(); T Stack(int size) { arr = new T[size]; } T void Push(T item) {…} T T Pop() {return arr[i]; } void Dispose() {top.Dispose();} } Создание объекта обобщенного типа : Необходимо указать все типы - параметры Stack myIntStack = new Stack (); Dictionary myDict = new Dictionary ();
Типов - параметров может быть много Обозначения типов – любые ( допустимые ) имена Обозначения типов могут использоваться в коде как обычный тип Для задания значения по умолчанию используется синтаксис Тип Переменная = default( Тип ); class MyDictionary where TKey : Complex, IComparable where TValue : class { } struct MyGenericStruct { } class MyGenericClass { C c = dafault(C); }
[ Модификаторы ] ВозвращаемыйТип ИмяМетода ( параметры ) [ Ограничения типов ] { } Примеры : void Swap (ref T a, ref T b) { T c = a; b = a; a = c; } public T Swap (T a, U b, Complex comp) {…} public T Copy (T a, T b) where T : new() { T result = new T(); …..} Использование : При вызове необходимо задать все типы параметры, если компилятор не может определить их из контекста Swap (ref comp1, ref comp2); int I = Swap (intVariable, longVariable, myIntComplexVariable);
[Модификаторы] interface ИмяИнтерфейса [Ограничения типов] {…} Пример : public interface MyInterface { T GetT(K k); K GerK(T t); T propertyT { get; } T propretyK { get; set; } bool Equal(T t, K k); } Использование : При реализации, либо класс должен быть обобщенным, либо должен реализовывать конкретный тип обобщенного интерфейса class MyClass : MyInterface { } class MyClass1 : MyInterface { } class MyClass2 : MyInterface { }
Типы - параметры : если что - то явно не оговорено, то этого НЕТ ! По умолчанию доступны только методы object Если нужны дополнительные методы Необходимо использовать ограничения
Интерфейсы where T : ICloneable, IDisposable Базовый класс where T : MyBaseClass Ссылочные типы / Типы значения where T : struct where T : class Нельзя одновременно указать и class, и struct Наличие конструктора по умолчанию ограничение должно быть последним в списке where T : new()
Нельзя требовать наличие операции Дублируйте обычными методами Нельзя требовать конструктора с параметрами Если указано несколько ограничений Все должны выполняться одновременно Если нужна альтернатива – используйте базовые интерфейсы
Обобщения и ограничения
Реализуйте Стек Стек должен быть обобщенным типом Методы void Push(T); T Pop(); T Top(); int Count(); В основном классе создайте обобщенный метод, создающий и заполняющий стек некоторым количеством объектов со значениями по умолчанию Создайте код для тестирования вашего стека Для желающих. Потребуйте от типа T, чтобы он реализовывал ICloneable и реализуйте T Top() так, чтобы он возвращал копию объекта, а не сам объект