Явная реализация интерфейса
30C# --- Руководство по C# --- Явная реализация интерфейса
Единственный класс или структура может реализовать любое количество интерфейсов. Из-за этого всегда существует вероятность реализации интерфейсов с членами, имеющими идентичные имена, и, следовательно, возникает необходимость в устранении конфликтов на уровне имен. При реализации члена интерфейса имеется возможность указать его имя полностью вместе с именем самого интерфейса. В этом случае получается явная реализация члена интерфейса, или просто явная реализация.
Когда один интерфейс наследует другой, то в производном интерфейсе может быть объявлен член, скрывающий член с аналогичным именем в базовом интерфейсе. Такое сокрытие имен происходит в том случае, если член в производном интерфейсе объявляется таким же образом, как и в базовом интерфейсе. Но если не указать в объявлении члена производного интерфейса ключевое слово new, то компилятор выдаст соответствующее предупреждающее сообщение.
Для явной реализации интерфейсного метода могут быть две причины. Во-первых, когда интерфейсный метод реализуется с указанием его полного имени, то такой метод оказывается доступным не посредством объектов класса, реализующего данный интерфейс, а по интерфейсной ссылке. Следовательно, явная реализация позволяет реализовать интерфейсный метод таким образом, чтобы он не стал открытым членом класса, предоставляющего его реализацию. И во-вторых, в одном классе могут быть реализованы два интерфейса с методами, объявленными с одинаковыми именами и сигнатурами. Но неоднозначность в данном случае устраняется благодаря указанию в именах этих методов их соответствующих интерфейсов. Рассмотрим каждую из этих двух возможностей явной реализации на следующем примере:
using System;
namespace ConsoleApplication1
{
public interface IName
{
void WriteName();
}
public interface INameFamily
{
// Объявляем в данном интерфейсе такой же метод
void WriteName();
void WriteFamily();
}
public interface IUserInfo : INameFamily
{
// Обязательно нужно указать ключевое слово new
// чтобы не скрывались методы базового интерфейса
new void WriteName();
void WriteUserInfo();
}
// Класс, реализующий два интерфейса
class UserInfo : IUserInfo,IName
{
string ShortName, Family, Name;
public UserInfo(string Name, string Family, string ShortName)
{
this.Name = Name;
this.Family = Family;
this.ShortName = ShortName;
}
// Используем явную реализацию интерфейсов
// для исключения неоднозначности
void IName.WriteName()
{
Console.WriteLine("Короткое имя: " + ShortName);
}
void INameFamily.WriteFamily()
{
Console.WriteLine("Фамилия: " + Family);
}
void INameFamily.WriteName()
{
Console.WriteLine("Полное имя: " + Name);
}
void IUserInfo.WriteName() { }
public void WriteUserInfo()
{
UserInfo obj = new UserInfo(Name, Family, ShortName);
// Для использования закрытых методов необходимо
// создать интерфейсную ссылку
IName link1 = (IName)obj;
link1.WriteName();
INameFamily link2 = (INameFamily)obj;
link2.WriteName();
link2.WriteFamily();
IUserInfo link3 = (IUserInfo)obj;
link3.WriteName();
}
}
class Program
{
static void Main()
{
UserInfo obj = new UserInfo(Name: "Alexandr", ShortName: "Alex", Family: "Erohin");
obj.WriteUserInfo();
Console.ReadLine();
}
}
}
Важно уяснить, что интерфейсы являются фундаментальным компонентом .NET Framework. Какого бы типа приложение не разрабатывалось (веб-приложение, приложение с настольным графическим интерфейсом, библиотека доступа к данными и т.п.), работа с интерфейсами будет обязательной частью этого процесса. Подводя итог всему изложенному, отметим, что интерфейсы могут приносить чрезвычайную пользу в следующих случаях:
При наличии единой иерархии, в которой только какой-то набор производных типов поддерживает общее поведение.
При необходимости моделировать общее поведение, которое должно встречаться в нескольких иерархиях, не имеющих общего родительского класса помимо System.Object.