Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теоретический_курс.doc
Скачиваний:
36
Добавлен:
10.11.2019
Размер:
7.68 Mб
Скачать

2. Явная реализация интерфейса

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

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

interface IControl

{

void Paint();

}

interface ISurface

{

void Paint();

}

class SampleClass : IControl, ISurface

{

// Оба интерфейса ISurface.Paint и IControl.Paint вызывают этот метод

public void Paint()

{

Console.WriteLine("Paint");

}

}

Однако, если члены двух интерфейсов не выполняют одинаковую функцию, это может привести к неверной реализации одного или обоих интерфейсов. Возможна явная реализация члена интерфейса — путём создания члена класса, который вызывается только через интерфейс и имеет отношение только к этому интерфейсу. Это достигается путем включения в имя члена класса имени интерфейса с точкой. Пример:

public class SampleClass : IControl, ISurface

{

void IControl.Paint()

{

System.Console.WriteLine("IControl.Paint");

}

void ISurface.Paint()

{

System.Console.WriteLine("ISurface.Paint");

}

}

Член класса IControl.Paint доступен только через интерфейс IControl, а член ISurface.Paint — только через интерфейс ISurface. Каждая реализация метода является независимой и недоступна в классе напрямую. Пример (вызов из метода Main программы):

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LC_Console

{

interface IControl

{

void Paint();

}

interface ISurface

{

void Paint();

}

public class SampleClass : IControl, ISurface

{

void IControl.Paint()

{

System.Console.WriteLine("IControl.Paint");

}

void ISurface.Paint()

{

System.Console.WriteLine("ISurface.Paint");

}

}

public class Program

{

static void Main()

{

SampleClass obj = new SampleClass();

//obj.Paint(); // Ошибка компилятора

IControl c = (IControl)obj;

c.Paint(); // Вызывает IControl.Paint из SampleClass

ISurface s = (ISurface)obj;

s.Paint(); // Вызывает ISurface.Paint из SampleClass.

Console.WriteLine("Для продолжение нажмите любую клавишу . . . ");

Console.ReadKey();

}

}

}

/* Выведет:

* IControl.Paint

* ISurface.Paint

* Для продолжение нажмите любую клавишу . . .

*/

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

interface ILeft

{

int P { get; }

}

interface IRight

{

int P();

}

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

class Middle : ILeft, IRight

{

public int P() { return 0; }

int ILeft.P { get { return 0; } }

}

В этом примере (ниже) выполняется объявление интерфейса, IDimensions, и класса, Box, который явно реализует члены интерфейса getLength и getWidth. Доступ к этим членам осуществляется через экземпляр интерфейса dimensions:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LC_Console

{

interface IDimensions

{

float getLength();

float getWidth();

}

class Box : IDimensions

{

float lengthInches;

float widthInches;

Box(float length, float width)

{

lengthInches = length;

widthInches = width;

}

// Явная реализация члена интерфейса

float IDimensions.getLength()

{

return lengthInches;

}

// Явная реализация члена интерфейса

float IDimensions.getWidth()

{

return widthInches;

}

static void Main()

{

// Объявляем экземпляр класса Box и передаём туда размеры

Box box1 = new Box(30.0f, 20.0f);

// Объявляем интерфейс получающий размеры

IDimensions dimensions = (IDimensions)box1;

// Две строки кода закомментированы так как вызовут ошибки компилятора

//Console.WriteLine("Length: {0}", box1.getLength());

//Console.WriteLine("Width: {0}", box1.getWidth());

// Выводит размеры из экземпляра класса Box c помощью методов из экземпляра интерфейса

Console.WriteLine("Длина: {0}", dimensions.getLength());

Console.WriteLine("Ширина: {0}", dimensions.getWidth());

}

}

}

/* Выведет:

* Длниа: 30

* Ширина: 20

* Для продолжение нажмите любую клавишу . . .

*/

Обратим внимание, что следующие строки в методе Main убраны в комментарий, так как иначе они вызвали бы ошибки компилятора. Член интерфейса, реализованный явным образом, недоступен из экземпляра класса:

//Console.WriteLine("Length: {0}", box1.getLength());

//Console.WriteLine("Width: {0}", box1.getWidth());

Обратите также внимание, что следующие строки в методе Main успешно печатают размеры поля, поскольку эти методы вызываются из экземпляра интерфейса:

Console.WriteLine("Длина: {0}", dimensions.getLength());

Console.WriteLine("Ширина: {0}", dimensions.getWidth());