Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Троелсен Э. Язык программирования С# 2010 и п...docx
Скачиваний:
113
Добавлен:
21.09.2019
Размер:
6.92 Mб
Скачать

Получение интерфейсных ссылок: ключевое слово as

Второй способ проверить поддержку интерфейса для данного типа предполагает использование ключевого слова as, о котором уже шла речь в главе 4. Если объект можно интерпретировать, как указанный интерфейс, будет возвращена ссылка на интерфейс. Если нет – вы получите null.

static void Main(string[] args) {

 …

 // Можно ли интерпретировать hex2, как IPointy?

 Hexagon hex2 = new Hexagon("Peter");

 IPointy itfPt2 = hex2 as IPointy;

 if (itfPt2 != null) Console.WriteLine("Вершин: {0}"itfPt2.Points);

 else Console.WriteLine("ОЙ! Вершин не видно…");

}

Обратите внимание на то, что при использовании ключевого слова as не возникает необходимости использовать логику try/catch, поскольку в том случае, когда ссылка оказывается непустой, вы гарантированно будете иметь действительную ссылку на интерфейс.

Получение интерфейсных ссылок: ключевое слово is

Можно также проверить реализацию интерфейса с помощью ключевого слова is. Если соответствующий объект не совместим указанным интерфейсом, будет возвращено значение false. А если тип совместим с интерфейсом, вы можете смело вызвать его члены без использования логики try/catch.

Для примера предположим, что мы изменили массив типов Shape так, что теперь некоторые его члены реализуют IPointy. Вот как с помощью ключевого слова is можно выяснить, какие из элементов в массиве поддерживают этот интерфейс.

static void Main(string[] args) {

 …

 Shape[] s = {new Hexagon(), new Circle(), new Triangle("Joe"), new Circle("JoJo")};

 for (int i = 0; i ‹ s.Length; i++) {

  // Напомним, что базовый класс Shape определяет абстрактный

  // член Draw(), поэтому все формы могут отображать себя.

  s[i].Draw()

  // Кто с вершинами?

  if (s[i] is IPointy) Console.WriteLine("-› Вершин: {0} ", ((IPointy)s[i]).Points);

  else Console.WriteLine("-› {0} без вершин!", s[i].PetName);

 }

}

Соответствующий вывод показан на рис. 7.2.

Рис 7.2. Динамическое обнаружение реализованных интерфейсов

Интерфейсы в качестве параметров

Поскольку интерфейсы являются полноценными типами .NET, вы можете конструировать методы, которые будут использовать интерфейсы, как параметры. Для примера предположим, что мы определили другой интерфейс с именем IDraw3D.

// Моделируем возможность отображения типа в пространстве.

public interface IDraw3D {

 void Draw3D();

}

Предположим также, что две из наших трех форм (Circle и Hexagon) сконфигурированы для поддержки этого нового поведения.

// Circle поддерживает IDraw3D.

public class Circle: Shape, IDraw3D {

 …

 public void Draw3D() {

  Console.WriteLine("3D-отображение окружности!");

 }

}

// Hexagon поддерживает IPointy и IDraw3D.

public class Hexagon: Shape, IPointy, IDraw3D {

 …

 public void Draw3D() { Console.WriteLine ("3D-отображение шестиугольника!"); }

}

На рис. 7.3 показана соответствующая обновленная диаграмма классов, полученная в Visual Studio 2005.

Рис. 7.3. Обновленная иерархия форм

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

// Создание нескольких форм.

// Если это возможно, их отображение в трехмерном виде.

public class Program {

 // Отображение форм, поддерживающих IDraw3D.

 public static void DrawIn3D(IDraw3D itf3d) {

  Console.WriteLine("-› Отображение IDraw3D-совместимого типа");

  itf3d.Draw3D();

 }

 static void Main() {

  Shape [] s = {new Hexagon(), new Circle(), new Triangle("Joe"), new Circle("JoJo")};

  for (int i = 0; i ‹ s.Length; i++) {

   …

   // Можно ли отобразить в 3D-виде?

   if (s[i] is IDraw3D) DrawIn3D((IDraw3D)s[i]);

  }

 }

}

Обратите внимание на то, "что треугольник не отображается, поскольку он не является IDraw3D-совместимым (рис. 7.4).

Рис.7.4. Интерфейсы в качестве параметров