Поиск

Реализация интерфейсов

Поскольку интерфейс определяет связь между фрагментами кода, любой класс, реализующий интерфейс, должен определять любой и каждый элемент этого интерфейса, иначе код не будет компилироваться. Используя IValidate из нашего примера, клиентский класс должен реализовать лишь методы интерфейса. В следующем примере есть базовый класс FancyControl и интерфейс IValidate. Кроме того, в нем имеется класс

MyControl, производный от FancyControl, реализующий интерфейс IValidate. Обратите внимание на синтаксис и способ приведения объекта MyControl к интерфейсу IValidate для ссылки на его члены.

using System;
public class FancyControl
{
protected string Data; public string data {
get {
return this.Data; }
set {
this.Data = value; } } }
interface IValidate {
bool ValidateO; }
class MyControl : FancyControl, IValidate {
public MyControlQ
{
data = "my grid data";
}
public bool ValidateO {
Console.WriteLine("Validating...{0}", data); return true;
} >
class InterfaceApp {
public static void Main() {
MyControl myControl = new MyControK);

// Вызов функции для размещения элемента управления // в форме. Теперь для проверки элемента управления // редактор может выполнить такие действия:

IValidate val = (IValidate)myControl;
bool success = val.ValidateO;
Console.WriteLineC'The validation of '{0}' was
{1 Successful", myControl.data,
(true == success ? "" : "not ")); } }

С помощью определения такого класса и интерфейса редактор может запрашивать у элемента управления, реализует ли он интерфейс IValidate (ниже я покажу, как это сделать). Если это так, редактор может проверить этот элемент управления, а затем вызывать реализованные методы интерфейса. Возможно, вы спросите: "А почему бы мне просто не определить базовый класс для использования в этом редакторе, у которого есть чисто виртуальная функция Validate! Ведь после этого редактор будет принимать только элементы управления, производные от этого базового класса, да?"

Да, но... это решение повлечет суровые ограничения. Допустим, вы создаете собственные элементы управления, каждый из которых является производным от гипотетического базового класса. Как следствие, все они реализуют этот виртуальный метод Validate. Это будет работать, пока в один прекрасный день вы не найдете по-настоящему замечательный элемент управления и вам захочется использовать его в редакторе. Допустим, вы нашли компонент "сетка", написанный кем-то другим и поэтому не являющийся производным от нужного редактору базового класса "элемент управления". На C++ решение заключается в том, чтобы с помощью множественного наследования сделать сетку производной от компонента стороннего разработчика и базового класса редактора одновременно. Но С# не поддерживает множественное наследование.
Интерфейсы позволяют реализовать несколько характеристик поведения в одном классе. На С# можно создавать объекты, производные от одного класса, и в дополнение к этой унаследованной функциональности реализовать столько интерфейсов, сколько нужно для класса. Например, чтобы приложение-редактор проверяло содержимое элемента управления, связывало элемент управления с базой данных и последовательно направляло его содержимое на диск, объявите свой класс так:

public class MyGrid : ThirdPartyGrid, IValidate.
ISerializable, IDataBound {
}

И все же вопрос остался: "Как отдельный фрагмент кода узнает, реализован ли классом данный интерфейс?"