возвращаемыйТип ИмяИнтерфейса.ИмяМетода(параметры) {}

Обратите внимание, что при использовании такого синтаксиса модификатор доступа не указывается: явно реализованные члены автоматически будут закрытыми. Например, такой синтаксис недопустим:

// Ошибка! Модификатор доступа не может быть указан!

public void IDrawToForm.Draw

{

   Console.WriteLine("Drawing to form...");

}

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

Console.WriteLine("***** Fun with Interface Name Clashes *****\n");

Octagon oct = new Octagon;

// Теперь для доступа к членам Draw должно

// использоваться приведение.

IDrawToForm itfForm = (IDrawToForm)oct;

itfForm.Draw;

// Сокращенная форма записи, если переменная типа

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

((IDrawToPrinter)oct).Draw;

// Также можно применять ключевое слово is.

if (oct is IDrawToMemory dtm)

{

  dtm.Draw;

}

Console.ReadLine;

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

<p id="AutBody_Root335">Проектирование иерархий интерфейсов</p>

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

Иерархии интерфейсов могут быть удобными, когда нужно расширить функциональность имеющегося интерфейса, не нарушая работу существующих кодовых баз. В целях иллюстрации создайте новый проект консольного приложения по имени InterfaceHierarchy. Затем спроектируйте новый набор интерфейсов, связанных с визуализацией, таким образом, чтобы IDrawable был корневым интерфейсом в дереве семейства:

namespace InterfaceHierarchy

{

  public interface IDrawable

  {

    void Draw;

  }

}

С учетом того, что интерфейс IDrawable определяет базовое поведение рисования, можно создать производный интерфейс, который расширяет IDrawable возможностью визуализации в других форматах, например:

namespace InterfaceHierarchy

{

  public interface IAdvancedDraw : IDrawable

  {

    void DrawInBoundingBox(int top, int left, int bottom, int right);

    void DrawUpsideDown;

  }

}

При таком проектном решении, если класс реализует интерфейс IAdvancedDraw, тогда ему потребуется реализовать все члены, определенные в цепочке наследования (в частности методы Draw, DrawInBoundingBox и DrawUpsideDown):

using System;

namespace InterfaceHierarchy

{

  public class BitmapImage : IAdvancedDraw

  {

    public void Draw

    {

      Console.WriteLine("Drawing...");

    }

    public void DrawInBoundingBox(int top, int left, int bottom, int right)

    {

      Console.WriteLine("Drawing in a box...");

    }

    public void DrawUpsideDown

    {

      Console.WriteLine("Drawing upside down!");

    }

  }

}

Перейти на страницу:

Похожие книги