Работа с объектами через интерфейсы. Операции is и as — КиберПедия 

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...

Работа с объектами через интерфейсы. Операции is и as

2019-09-26 413
Работа с объектами через интерфейсы. Операции is и as 0.00 из 5.00 0 оценок
Заказать работу

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

Результат операции равен true, если объект можно преобразовать к заданному типу, и false в противном случае. Операция обычно используется в следующем контексте:

{

// выполнить преобразование "объекта" к "типу"

// выполнить действия с преобразованным объектом

}

Допустим, мы оформили какие-то действия с объектами в виде метода с параметром типа object. Прежде чем использовать этот параметр внутри метода для обращения к методам, описанным в производных классах, требуется выполнить преобразование к производному классу. Для безопасного преобразования следует проверить, возможно ли оно, например так:

static void Act(object A)

{

if (A is IAction)

{

   IAction Actor = (IAction) A;

   Actor.Draw();

}

}

В метод Act можно передавать любые объекты, но на экран будут выведены только те, которые поддерживают интерфейс IAction.

Недостатком использования операции is является то, что преобразование фактически выполняется дважды: при проверке и при собственно преобразовании. Более эффективной является другая операция — as. Она выполняет преобразование к заданному типу, а если это невозможно, формирует результат null, например:

static void Act(object A)

{

IAction Actor = A as IAction;

if (Actor!= null) Actor.Draw();

}

Обе рассмотренные операции применяются как к интерфейсам, так и к классам.

Интерфейсы и наследование

Интерфейс может не иметь или иметь сколько угодно интерфейсов-предков, в последнем случае он наследует все элементы всех своих базовых интерфейсов, начиная с самого верхнего уровня.

Как и в обычной иерархии классов, базовые интерфейсы определяют общее поведение, а их потомки конкретизируют и дополняют его. В интерфейсе-потомке можно также указать элементы, переопределяющие унаследованные элементы с такой же сигнатурой. В этом случае перед элементом указывается ключевое слово new, как и в аналогичной ситуации в классах. С помощью этого слова соответствующий элемент базового интерфейса скрывается. Класс, реализующий интерфейс, должен определять все его элементы, в том числе унаследованные.

Интерфейс, на собственные или унаследованные элементы которого имеется явная ссылка, должен быть указан в списке предков класса.

Класс наследует все методы своего предка, в том числе те, которые реализовывали интерфейсы. Он может переопределить эти методы с помощью спецификатора new, но обращаться к ним можно будет только через объект класса. Если использовать для обращения ссылку на интерфейс, вызывается не переопределенная версия:

interface IBase 

void A(); 

class Base: IBase 

public void A() {... } 

class Derived: Base

new public void A() {... } 

...

Derived d = new Derived (); 

d.A();                   // вызывается Derived.A(); 

IBase id = d; 

id.A();                  // вызывается Base.A();

Однако если интерфейс реализуется с помощью виртуального метода класса, после его переопределения в потомке любой вариант обращения (через класс или через интерфейс) приведет к одному и тому же результату. Метод интерфейса, реализованный явным указанием имени, объявлять виртуальным запрещается.

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

interface IBase 

void A(); 

class Base: IBase 

void IBase.A() {... }   // не используется в Derived

class Derived: Base, IBase

public void A() {... } 

}

Если класс наследует от класса и интерфейса, которые содержат методы с одинаковыми сигнатурами, унаследованный метод класса воспринимается как реализация интерфейса. Вообще при реализации интерфейса учитывается наличие "подходящих" методов в классе независимо от их происхождения. Это могут быть методы, описанные в текущем или базовом классе, реализующие интерфейс явным или неявным образом.

Стандартные интерфейсы.NET

В библиотеке классов.NET определено множество стандартных интерфейсов, задающих желаемое поведение объектов. Например, интерфейс IComparable задает метод сравнения объектов на больше-меньше, что позволяет выполнять их сортировку. Реализация интерфейсов IEnumerable и IEnumerator дает возможность просматривать содержимое объекта с помощью конструкции foreach, а реализация интерфейса ICloneable — клонировать объекты.

Стандартные интерфейсы поддерживаются многими стандартными классами библиотеки. Например, работа с массивами с помощью цикла foreach возможна именно потому, что тип Array реализует интерфейсы IEnumerable и IEnumerator. Можно создавать и собственные классы, поддерживающие стандартные интерфейсы, что позволит использовать объекты этих классов стандартными способами.

Сравнение объектов

Интерфейс IComparable определен в пространстве имен System. Он содержит всего один метод CompareTo, возвращающий результат сравнения двух объектов — текущего и переданного ему в качестве параметра:

interface IComparable

{

int CompareTo(object obj)

}

Метод должен возвращать:

· 0, если текущий объект и параметр равны;

· отрицательное число, если текущий объект меньше параметра;

· положительное число, если текущий объект больше параметра.

Реализуем интерфейс IComparable в знакомом нам классе Monster. В качестве критерия сравнения объектов выберем поле health. В листинге 9.1 приведена программа, сортирующая массив монстров по возрастанию величины, характеризующей их здоровье.

using System;

namespace ConsoleApplication1

{

class Monster: IComparable

{

   public Monster(int health, int ammo, string name)

   {

       this.health = health;

       this.ammo = ammo;

       this.name = name;

   }

       

   virtual public void Passport()

   {

       Console.WriteLine("Monster {0} \t health = {1} ammo = {2}",

                          name, health, ammo);

   }

   public int CompareTo(object obj)     // реализация интерфейса

   {

       Monster temp = (Monster) obj;

       if (this.health > temp.health) return 1;

       if (this.health < temp.health) return -1;

       return 0;

   }

   string name;

   int health, ammo;

}

class Class1

{ static void Main()

   {

       const int n = 3;

      Monster[] stado = new Monster[n];

       stado[0] = new Monster(50, 50, "Вася");

       stado[1] = new Monster(80, 80, "Петя");

       stado[2] = new Monster(40, 10, "Маша");

       Array.Sort(stado);          // сортировка стала возможной

       foreach (Monster elem in stado) elem.Passport();

   }

}

}

Листинг 1. Пример реализации интерфейса IComparable

Результат работы программы:

Monster Маша health = 40 ammo = 10

Monster Вася health = 50 ammo = 50

Monster Петя health = 80 ammo = 80

Во многих алгоритмах требуется выполнять сортировку объектов по различным критериям. В C# для этого используется интерфейс IComparer, который мы рассмотрим далее.


Поделиться с друзьями:

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.023 с.