Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

public interface IDrawable

{

void Draw;

int TimeToDraw => 5;

}

Теперь обновите операторы верхнего уровня:

Console.WriteLine("***** Simple Interface Hierarchy *****");

...

if (myBitmap is IAdvancedDraw iAdvDraw)

{

iAdvDraw.DrawUpsideDown;

Console.WriteLine($"Time to draw: {iAdvDraw.TimeToDraw}");

}

Console.ReadLine;

Этот

код не только скомпилируется, но и выведет значение
5
при вызове метода
TimeToDraw
. Дело в том, что стандартные реализации попадают в производные интерфейсы автоматически. Приведение
BitMapImage
к интерфейсу
IAdvancedDraw
обеспечивает доступ к методу
TimeToDraw
, хотя экземпляр
BitMapImage
не имеет доступа к стандартной реализации. Чтобы удостовериться в этом, введите следующий код, который вызовет ошибку на этапе компиляции:

// Этот код не скомпилируется

myBitmap.TimeToDraw;

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

TimeToDraw
из
IAdvancedDraw
занимает 15 единиц времени, то модифицируйте определение интерфейса следующим образом:

public interface IAdvancedDraw : IDrawable

{

void DrawInBoundingBox(

int top, int left, int bottom, int right);

void DrawUpsideDown;

new int TimeToDraw => 15;

}

Разумеется, в классе

BitMapImage
также можно реализовать метод
TimeToDraw
. В отличие от метода
TimeToDraw
из
IAdvancedDraw
в классе необходимо только реализовать метод без его сокрытия.

public class BitmapImage : IAdvancedDraw

{

...

public int TimeToDraw => 12;

}

В случае приведения экземпляра

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

// Всегда вызывается метод на экземпляре:

Console.WriteLine("***** Calling Implemented TimeToDraw *****");

Console.WriteLine($"Time to draw: {myBitmap.TimeToDraw}");

Console.WriteLine($"Time to draw: {((IDrawable) myBitmap).TimeToDraw}");

Console.WriteLine($"Time to draw: {((IAdvancedDraw) myBitmap).TimeToDraw}");

Вот результаты:

***** Simple Interface Hierarchy *****

...

***** Calling Implemented TimeToDraw *****

Time to draw: 12

Time to draw: 12

Time to draw: 12

Множественное

наследование с помощью интерфейсных типов

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

MiInterfaceHierarchy
. Здесь имеется еще одна коллекция интерфейсов, которые моделируют разнообразные абстракции, связанные с визуализацией и фигурами. Обратите внимание, что интерфейс
IShape
расширяет и
IDrawable
, и
IPrintable
:

// IDrawable.cs

namespace MiInterfaceHierarchy

{

// Множественное наследование для интерфейсных типов - это нормально.

interface IDrawable

{

void Draw;

}

}

// IPrintable.cs

namespace MiInterfaceHierarchy

{

interface IPrintable

{

void Print;

void Draw; // < -- Здесь возможен конфликт имен!

}

}

// IShape.cs

namespace MiInterfaceHierarchy

{

// Множественное наследование интерфейсов. Нормально!

interface IShape : IDrawable, IPrintable

{

int GetNumberOfSides;

}

}

На рис. 8.6 показана текущая иерархия интерфейсов.

Главный вопрос: сколько методов должен реализовывать класс, поддерживающий

IShape
? Ответ: в зависимости от обстоятельств. Если вы хотите предоставить простую реализацию метода
Draw
, тогда вам необходимо реализовать только три члена, как иллюстрируется в следующем типе
Rectangle
:

using System;

namespace MiInterfaceHierarchy

{

class Rectangle : IShape

{

public int GetNumberOfSides => 4;

public void Draw => Console.WriteLine("Drawing...");

public void Print => Console.WriteLine("Printing...");

}

}

Если вы предпочитаете располагать специфическими реализациями для каждого метода

Draw
(что в данном случае имеет смысл), то конфликт имен можно устранить с использованием явной реализации интерфейсов, как делается в представленном далее типе
Square
:

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