Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по ООП (язык C#).pdf
Скачиваний:
190
Добавлен:
16.05.2015
Размер:
1.54 Mб
Скачать

Чернов Э. А.

- 83 -

Лекции по языку C# v 2.3

Ограничения типа where T: struct и where T: class имеют в виду не конкретный класс или структуру, а только тип. Ограничение where T: new() применяется в случаях, при которых требуется передавать объекты в подпрограммы.

Интерфейсы

Интерфейсом называется класс, содержащий набор абстрактных методов для реализации некоторых действий, обычно, вспомогательных по отношению к основной операции. Абстрактные методы, по определению, реализации не имеют. Они требуют явного переопределения. Применение стандартных интерфейсов предоставляет пользователю полный набор методов для реализации требуемого действия. С другой стороны, компилятор обеспечивает частичную реализацию абстрактных методов.

Интерфейсы бывают обобщенные и необобщенные. В данном разделе рассмотрены необобщенные интерфейсы. Обобщенные интерфейсы будут рассмотрены далее после обобщений вместе с коллекциями.

Рассмотрим интерфейсы, например, для реализации операции сравнения. Сравнить два числа можно, написав логическое отношение, скажем: a > b. Ситуация изменяется, если требуется сравнить два объекта, обладающих рядом атрибутов, которые должны учитываться при сравнении по одному или в некоторой взаимосвязи друг с другом. Характерным примером является выбор для товара лучшего соотношения цены и качества, причем качество, как правило, определяется набор свойств.

Реализации сравнения помогают интерфейсы IComparable и IComparator. (В языке C# принято имена интерфейсов начинать с буквы I). Первый из них задает возможность сравнения текущего объекта (описанного в классе, который наследует интерфейс IComparable) с заданным объектом такого же типа. Интерфейс IComparator позволяет сравнивать два независимых объекта.

Интерфейс IComparable имеет абстрактный метод CompareTo, имеющий формат:

public int CompareTo(<имя класса> obj) // Пример записи

В примере ниже при оформлении метода записан параметр общего класса object, от которого наследуются все классы. Затем объект этого класса преобразуется в локальный объект основного класса (b = (shirt) obj;). Это сделано для того, чтобы можно было сравнивать два соседних элемента в списке, один из которых текущий (слева от знака равенства), а другой следующий в списке (передается как параметр).

Чернов Э. А.

- 84 -

Лекции по языку C# v 2.3

Метод CompareTo возвращает целое число, указывающее на соотношение между объектами, как указано в таблице. Это число указывает на порядок следования объектов друг за другом, позволяя гибко устанавливать порядок сортировки:

Возвращаемое

Смысл

число

 

Меньше нуля Данный объект меньше объекта, заданного в виде параметра.

Нуль

Данный объект и объект, заданный в виде параметра, равны.

Больше нуля. Данный объект больше объекта, заданного в виде параметра.

Ниже приведена программа, в которой формируется список рубашек. Для рубашки задано всего 3 атрибута: фасон, размер и цена. Листинг программы для реализации сортировки рубашек по цене.

// Программа для иллюстрации необобщенного интерфейса IComparable. class shirt : IComparable

{

int size;

// Размер

string fashion;

// Фасон

int price;

// Цена

public shirt( string f, int p, int s) // Конструктор с параметрами

{

size = s; fashion = f; price = p;

}

public string Fash // Свойство для фасона

{

get { return fashion; } set { fashion = value; }

}

public int Price // Свойство для цены

{

get { return price; } set { price = value; }

}

public int Size // Свойство для размера

{

get { return size; } set { size = value; }

}

// Реализация метода CompareTo для интерфейса IComparable. public int CompareTo(object obj)

{

shirt b;

// Объявление локального объекта

b = (shirt) obj;

// Приведение типа

int n = price.CompareTo(b.price); // Выполнение сравнения

Чернов Э. А.

- 85 -

Лекции по языку C# v 2.3

return n;

}

}

class IComparableDemo

{

static void Main()

{

ArrayList sh = new ArrayList(); // Объявление пустого списка

// Формирование списка.

sh.Add(new shirt("Libera Vita", 2250, 44)); sh.Add(new shirt("Broadway", 1760, 42)); sh.Add(new shirt("Sela", 1000, 48)); sh.Add(new shirt("Selected Homme", 2570, 48));

Console.WriteLine("Список рубашек до сортировки:"); foreach (shirt ob in sh)

Console.WriteLine("Фасон {0,-15} Стоимость: {1,4:D} Размер: {2}", ob.Fash, ob.Price, ob.Size);

// Сортировка списка с помощью встроенного метода. sh.Sort();

Console.WriteLine("\n Список рубашек после сортировки по цене:"); foreach (shirt ob in sh)

Console.WriteLine("Фасон {0,-15} Стоимость: {1,4:D} Размер: {2}", ob.Fash, ob.Price, ob.Size);

Console.ReadKey();

}

}

Ниже приведен результат выполнения программы.

Если в методе CompareTo заменить строку выполнения сравнения:

int n = price.CompareTo(b.price); // Выполнение сравнения

строкой, приведенной ниже (а также заменить текст заголовка таблицы после сортировки), то произойдет сортировка по фасону

int n = fashion.CompareTo(b.fashion);

Чернов Э. А.

- 86 -

Лекции по языку C# v 2.3

Результат будет таким:

 

 

Способы выбора режима сортировки во время выполнения программы будут рассмотрены далее.

Для сравнения можно применять обобщенные интерфейсы IComparable<T> и IComparer<T>. Как следует из названия, интерфейс IComparable<T> предусматривает возможность выполнения сравнения. Интерфейс IComparable<T>, когда T определен, позволяет сравнивать текущий объект (объект описан в том же классе, в котором выполняется сравнение) с другим объектом того же типа. Интерфейс IComparer<T> (дословно «сравниватель») используется для сравнения двух объектов T, обычно вне самих объектов T. Таким образом, объявление:

class MyClass : IComparable<T>

Вряд ли имеет смысл, поскольку MyClass и T не связаны друг с другом. С другой стороны запись ниже показывает, как это следует делать:

class T : IComparable<T>

{

public int CompareTo(T other) // Сравнить с другим

{

// Операторы для выполнения сравнения...

}

}

Интерфейс IComparer<T> может быть полезен, когда требуется выполнить сортировку, задавая определенный пользователем порядок следования объектов. Например, класс Product можно сортировать по цене (основной порядок следования элементов), но можно сортировать и по названию товара. Это можно выполнить так:

public class Product: IComparable <Product>

{

public string Name { get; set; } public int Price { get; set; } public Product() { } //

// Реализация метода CompareTo (по цене) для интерфейса IComparable. public int CompareTo(Product obj)

{

Чернов Э. А.

- 87 -

Лекции по языку C# v 2.3

Product b;

// Объявление локального объекта

b = (Product)obj;

// Приведение типа

int n = Price.CompareTo(b.Price); // Выполнение сравнения return n;

}

}

//Сравнение товаров по названию (класс задает сравнение по названию)

//имя NameComparer может быть любым Правка, где NameComparer? public class: IComparer<Product>

{

//Вызов общего метода сравнения

public int Compare(Product a, Product b)

{

if (a.Name.CompareTo(b.Name) != 0)

{// Переключение метода сравнения CompareTo на название товара return a.Name.CompareTo(b.Name);

}

else return 0;

}

}

class Program

{

static void Main(string[] args)

{

List<Product> lstProd = new List<Product>()

{

new Product{Name="Пицца",Price=83}, new Product{Name="Багет", Price=65}, new Product{Name="Пирог",Price=35}, new Product{Name="Орбит",Price=25}, new Product{Name="Фанта",Price=48}, new Product{Name="Пепси",Price=88}

};

Console.WriteLine("Исходный массив"); foreach (Product prod in lstProd)

Console.WriteLine("{0} \t{1}",prod.Name, prod.Price);

//Сортировка по умолчанию, определено методом CompareTo lstProd.Sort();

Console.WriteLine("\nПосле сортировки по цене"); foreach (Product prod in lstProd)

Console.WriteLine("{0} \t{1}",prod.Name, prod.Price);

//Изменение порядка сортировки интерфейсом IComparer Console.WriteLine("\n После сортировки по названию"); NameComparer pc = new NameComparer();

lstProd.Sort();

foreach (Product prod in lstProd) Console.WriteLine("{0} \t{1}",prod.Name, prod.Price);

Console.ReadKey();

}

}