Интерфейсы C#
Всем доброго времени суток. На связи Алексей Гулынин. В прошлой статье вы узнали про статические поля и методы в C#. В данной статье я бы хотел поговорить про интерфейсы в C#. При наследовании в C# в качестве родительского класса можно указать один и только один класс. Это не всегда бывает удобно. Для решения данной проблемы в C# вводится понятие интерфейса. В интерфейсе описываются только заголовки методов. Когда мы создаём класс, то можем указать, что данный класс реализует один интерфейс или сразу несколько.
Когда класс говорит, что он реализует какой-то интерфейс, класс гарантирует что внутри него (класса) реализованы все методы, которые описаны в интерфейсе. Интерфейс — это контракт, который необходимо исполнить классом.
Особенности интерфейсов:
- Только заголовки методов.
- Реализация методов отсутствует.
- Нельзя создать экземпляр интерфейса, однако, можно создать переменную типа интерфейса, ведь это ссылочный тип данных. Такая переменная может указывать на объект класса, реализующего данный интерфейс.
- Перед методом не нужно ставить "public", т.к. метод в интерфейс по умолчанию является "public" и "virtual".
Интерфейс может быть реализован также структурами.
Интерфейс создаётся с помощью ключевого слова "interface". Перед ключевым словом можно указать "public" или "internal" (по умолчанию, если ничего не указано):
public interface IFlyable { }
Что можно описать внутри интерфейсов:
- Заголовки методов.
- Можно описать свойства (properties), т.е. они не являются полями, это методы "get" и "set".
- Индексатор (индексирующее property), т.к. это тоже метод.
- Делегаты.
Как записать, что класс реализует интерфейс:
public class Animal: IFlyable { }
В данном случае мы указали, что класс "Animal" реализует интерфейс "IFlyable".
Если класс-родитель реализует какой-либо интерфейс, то считается, что и класс-наследник реализует данный интерфейс. В классе-наследнике реализацию можно переопределить.
По рекомендации Microsoft перед названием всех интерфейсов нужно ставить букву "I". Технически, конечно, и без этого всё будет работать.
Интерфейс можно реализовать двумя способами:
1) Напрямую в классе, просто реализуя метод.
2) Прямая реализация метода интерфейса. В данном случае в классе создаётся метод, у которого не указывается уровень доступа, в качестве имени метода идёт имя интерфейса и имя метода. Это приведёт к тому, что не получится вызвать этот метод через ссылку самого объекта класса, можно вызывать только через ссылку типа интерфейса.
Интересный момент заключается в том, что можно сделать сразу двумя способами, причем по-разному реализовав, и это не будет перегрузкой, т.к. параметры будут одни и те же (и одного и того же типа). Вызов данных методов зависит от типа ссылки, через которую они вызываются. В реальности обычно так не делают. Зачем так сделали мне, лично, непонятно.
Давайте на примере рассмотрим, как создавать и реализовывать интерфейсы:
// Что-то что летает public interface IFlyable { void fly(); } // Животное, которое может летать public class Bird : IFlyable { // 1 способ реализации интерфейса public void fly() { Console.WriteLine("Птица полетела..."); } // 2 способ реализации интерфейса void IFlyable.fly() { Console.WriteLine("Птица не полетела. Странно..."); } } class Program { static void Main(string[] args) { // Создадим переменную класса Bird Bird bird1 = new Bird(); bird1.fly(); // выйдет "Птица полетела..." // Создадим переменную типа IFlyable IFlyable bird2 = new Bird(); bird2.fly(); // выйдет "Птица не полетела. Странно..." // Если мы закоментируем метод "void IFlyable.fly()", то птица в обоих случаях полетит Console.ReadLine(); } }
Существует набор уже готовых интерфейсов, которые бывает полезно реализовать в собственных классах. Например, интерфейс "IComparable", который состоит из одного единственного метода "int CompareTo(Object obj)". Данный интерфейс даёт возможность сортировки объектов в коллекции. Для сортировки нужно уметь сравнивать 2 значения. Если это строки или числа, то здесь вопросов нет, а вот с объектами непонятно. Как сравнить, что один объект больше другого? А это вы сами должны описать в реализации этого интерфейса.
Существует также интерфейс "IComparer", который сравнивает 2 объекта. В нём также один метод "int Compare (Object obj1, Object obj2)".
В качестве домашнего задания: попробуйте в класс "Room", который мы создали на одном из прошлых занятий по C#, добавить реализацию интерфейса "IComparable". Также создайте статический класс, который будет реализовывать интерфейс "IComparer". В качестве сравнения используйте площадь комнат.
На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.