Особенности реализации интерфейсов
Неявная реализация
Неявный способ аналогичен способу реализации интерфейсов в C++ и заключается в простой реализации в классе или структуре методов с совпадающей сигнатурой методов интерфейса.
При реализации интерфейса в структуре должны быть реализованы все методы наследованных интерфейсов. В случае реализации интерфейсов в классе, реализация части (или всех) методов может быть заменена декларацией абстрактных методов.
Неявная реализация
Явная реализация используется при реализации интерфейсов, содержащих функции с одинаковыми именами и сигнатурами и заключающаяся в указании полного имени метода, например object IConeable.Clone().
Данный способ — явное указание компилятору, метод какого именно интерфейса реализуется. Именно поэтому (я предполагаю) данный способ и назвали явной реализацией. При явной реализации интерфейса все методы интерфейса реализуются как виртуальные и закрытые.
Реализация интерфейса ICloneable
public struct Cloneable : ICloneable
{
private Cloneable(Cloneable copy)
{
}
// .method public hidebysig instance valuetype Interfaces.Cloneable
// Clone() cil managed
public Cloneable Clone()
{
return new Cloneable(this);
}
// .method private hidebysig newslot virtual final
// instance object System.ICloneable.Clone() cil managed
object ICloneable.Clone()
{
return new Cloneable(this);
}
}
В структуре объявлены два метода с одинаковым именем Clone. Метод Clone объекта, возвращает объект типа Cloneable (размерный тип). Данный метод не виртуальный. Явно реализованный метод Clone интерфейса Icloneable, возвращает интерфейс, виртуальный, и закрытый.
Данный метод реализации следует использовать с осторожностью, так как это влечет за собой определенные неудобства в использовании:
- Явно реализованный метод интерфейса виртуальный и закрытый (final), следовательно, он не может быть переопределен в классе-наследнике, несмотря на то, что является виртуальным;
- Явно реализованный метод можно вызвать только приведя указатель на объект к указателю на интерфейс. Приведение необходимо сделать не только во внешнем коде, но и в методах самого объекта, и в методах объектов, наследованных от класса, в котором находится явная реализация интерфейса;
- При вызове явно реализованного метода интерфейса у экземпляра размерного типа происходит его упаковка;
Реализация свойств
Если в интерфейсе декларировано свойство с одним методом, например get, при реализации данного интерфейса свойство можно дополнить методом set. Т.е. декларация свойства не накладывает ограничений на то, как именно оно должно быть реализовано.
В следующем примере декларирруется публичный интерфейс и закрытый класс, его реализующий. Имя объекта можно прочитать в любой сборке приложения, тогда как изменить его можно только внутри данной сборки.
namespace Lib { public interface INamed { string Name { get; } } internal class Implementation : INamed { private string _name; public Implementation(string name) { _name = name; } public string Name { get { return _name; } set { _name = value; } } } public static class API { public static INamed GetNamed() { return new Implementation("test"); } } }