Интерфейсы
Если в абстрактном классе объявить только абстрактные функции, то можно полностью отделить интерфейс всего класса от реализации самого класса. Будет ли это реализовано в абстрактном классе или нет, в общем, то зависит от дисциплины программиста, или будем говорить, от его желания.
В C# для определения интерфейса класса введены специальные классы, которые так и называются – интерфейсы. Интерфейсы подобны абстрактным классам, но в отличие от них:
1. Ни при каких условиях не поддерживает реализацию методов (нет тела).
2. По умолчанию в интерфейсе устанавливается спецификация public.
3. Все методы интерфейса являются абстрактными, т.е. чистыми виртуальными функциями.
4. Для интерфейсов в C# разрешено множественное наследование.
Синтаксис объявления интерфейса выглядит следующим образом:
interface name
{
:
: // методы
}
Например:
interface Infs
{
void frn(int z);
int maxin(int a, int b);
}
Кроме методов интерфейсы могут содержать свойства, индексаторы и
события:
interface Inf
{
:
|
|
int Propr {get; set;} //Свойство
string this [int index] {get; set;} //Индексатор
}
После объявления интерфейса он может быть реализован с помощью класса. Для этого класс, реализующий интерфейс, образуется путем наследования от интерфейса (помните, что интерфейс это специальный класс).
Синтаксис наследования для реализации интерфейса:
class class_name: interface_name
{
// тело класса
}
От одного интерфейса может быть порождено сколь угодно много классов.
Класс может реализовать несколько интерфейсов. Для этого используется множественное наследование:
class class_name: interface_name1, interface_name2,..., interface_nameN
{
: // тело класса
}
Возможно смешанное наследование, т.е. класс наследник порождается от одного базового класса и одного или нескольких интерфейсов:
class class_name: class_base, interface_name1,..., interface_nameN
{
: // тело класса
}
Новый интерфейс можно получить с помощью наследования путем порождения его из одного или нескольких интерфейсов:
interface name: interface_name1[,..., interface_nameN]
{
: // методы
}
В классе реализующий интерфейс, код всех методов интерфейса, в том числе и родителей интерфейса, должен быть определен.
Если клиент попытается вызвать метод класса, который в нем не реализован, то произойдет ошибка периода исполнения. Для того, чтобы избежать такой ситуации можно использовать оператор is, который позволяет проверять во время выполнения совместимость одного типа с другим.
Синтаксис оператора is:
выражение is тип
Если выражение слева может быть приведено к типу указанному от оператора is справа, то оператор is возвращает значение true (истина).
Важно понимать, что при приведении типов, класс наследник всегда может быть приведен к базовому классу. Класс наследник считается по своим возможностям шире класса родителя, и он может быть преобразован к родительскому классу путем усечения. Из большего всегда можно получить меньшее, но не наоборот. Класс, реализующий интерфейс, является производным от интерфейса. Следовательно, объект этого класса всегда может быть преобразован к интерфейсу, от которого порожден класс.
|
|
Пример:
using System;
namespace ConsoleApplication11
{
class CA
{
protected string Dt;
protected string data
{
get
{
return "Строка: "+Dt;
}
set
{
Dt = value;
}
}
}
interface IOutInp
{
bool Set ();
bool Put ();
}
class CD:CA
{
public CD()
{
data = "Class CD";
}
}
class CB:CA,IOutInp
{
public void MySet()
{
data = "Hello";
}
public bool Put()
{
Console.WriteLine(data);
return true;
}
public bool Set()
{
Console.WriteLine("Введите строку символов");
data = Console.ReadLine();
return true;
}
}
class Class1
{
static void Main(string[] args)
{
CB pb = new CB();
CD pD = new CD();
pb.MySet();
if(pb is IOutInp) //запрос интерфейса
{
pb.Put();
pb.Set();
pb.Put();
}
else
{
Console.WriteLine("Error");
}
}
}
}
Результат работы программы:
Строка: Hello